I have a class that has a parameterless constructor that I want to remove (or make private)
class C
{
string A { get; set; }
int B { get; set; }
public C() { } //Problem
public C(A a, B b)
{
A = a;
B = b;
}
}
Problem is, the code base is littered with hundreds of expressions such as new C {A = a, B = b}, or new C() { B = b, A = a }, in every conceivable variation, ordering of fields, etc. (I didn't know that the brackets were optional until today).
Is there any automated way of fixing up my code to use the 2 argument constructor? The changes are trivial, but I think I'll go insane if I have to do it manually.
My examples have 5 or 6 arguments, and not all are required, etc.
(The motivation is to make the class immutable. Hiding the parameterless constructor and the public setters is the first step)
I've had a small amount of success with regular expressions (Notepad++'s regex support seems to stop after 4 captures), but writing a complex regex to fix 6 items at a time doesn't actually save me a great deal.
You can use the ability to explicitly specify named arguments in a function call (including a constructor) to fix this relatively easily.
Specifically, you can replace
C() { B = b, A = a }
with
C(B: b, A: a)
and the constructor will behave correctly. This will work regardless of the order of the arguments, so long as they're all either specified or optional.
Here's an entirely different approach you can try:
Do exactly what you want to do to C. Then create a CBuilder class which has all the same properties as a C, but only has a single method:
public C Convert()
{
return new C(this.A, this.B);
}
Then, you just need to do a find/replace on new C() {...}; and change it into (new CBuilder() {...}).Convert();, which would be a single regex replacement.
This doesn't immediately solve the problem, but it does let you refactor freely, and you can make it policy that every time you work on something that uses CBuilder, you replace that instance of it with a C instead. Gradually, you'll refactor all the code, but it won't prevent you from moving forward.
Suggestion: Maybe you could make use of named parameters.
new C {A = 5, B = "tt"} is in the end equivalent to new C(A: 5, B: "tt")
So you could replace all occurences of "A =" into "A:" and "B =" into "B :"
This could be easier with temporary rename of A into NewNameForANotCollidingWithAnything so that you can do massive blind automated and safe replace.
Then replace "new C{...}" into new "C (...)" // this is the most difficult part (I did not try it)
Hope it takes you closer to what you need....
Remove your parameterless constructor completely. The compiler will fail on all it's uses and you can switch to use the 2-parameter version.
Related
Can any one help me on this problem.
void method1 ( string A, datatype_1 B, string C) {};
void method2 ( string A, datatype_2 B, string C) {};
Above is my sudo code, I have two methods, method 1 and 2, the logic are 99% identical. Method parameters are almost identical, except for datatype_1, and datatype_2. Is there a way that I can only write one method, and the parameter for datatype_1&2 there's a syntax can detect what kind of data type I passed into?
background:
these two methods are OAuth Post method. datatype_1 and 2 which they are 'StringContent' and 'HttpContent'. requests use either one of the Content type.
is there a way :void method (string A, datatype_1 ? datatype_2 B, string C) {}; ??
Thanks a lot.
I believe you are looking for a generic method. If you implement them in your function you can use it like so with type checking to do different things with the different types that are passed:
void method<T> ( string A, T B, string C) {
if(B == typeof(datatype_1){}
if(B == typeof(datatype_2){}
};
method<datatype_1>(arg1,arg2,arg3);
method<datatype_2>(arg1,arg2,arg3);
This way you can combine the logic for both methods since there is so much overlap between them. Generics are an important way to reduce the amount of redundant code in your codebase.
First, I don't have much experience in .Net - especially within the last 7 years.
I'm trying to develop an application and would to incorporate another library (https://github.com/Giorgi/Math-Expression-Evaluator)
That library allows me to evaluate math expressions like Evaluate("a+b", a: 1,b: 1). The method signature is public decimal Evaluate(string expression, object argument = null)
I would like to understand better how .Net translates comma-separated arguments into a single "argument".
I'm not sure how to create that argument dynamically.. for example, iterating through a list of values and creating an object that will match the appropriate argument for that signature.
I'm really just looking for pointers for documentation and more information.. Thanks for anything.
EDIT: Sorry.. purposely left it broad because I wasn't looking for people to do my work for me.. just can't seem to find a starting point to do my own research.
The method is called like
dynamic engine = new ExpressionEvaluator() ;
engine.Evaluate("(c+b)*a", a: 6, b: 4.5, c: 2.6)) ;
In the body of Evalute() is this code (which turns that argument into a Dictionary of String, Decimal pairs.
if (argument == null)
{
return new Dictionary<string, decimal>();
}
var argumentType = argument.GetType();
var properties = argumentType.GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Where(p => p.CanRead && IsNumeric(p.PropertyType));
var arguments = properties.ToDictionary(property => property.Name,
property => Convert.ToDecimal(property.GetValue(argument, null)));
return arguments;
What I'd like to be able to do is parse a String like "a:1,b:2" and turn it into an object that matches that Evaluate() signature.
That library is using high level magic... Very high level :-)
The trick is that the class is declared as:
public class ExpressionEvaluator : DynamicObject
So it is a class that implements the dynamic magic introduced in .NET 4.0
Now... In the class there are two Evaluate methods:
public decimal Evaluate(string expression, object argument = null)
and
private decimal Evaluate(string expression, Dictionary<string, decimal> arguments)
The only method normally visible and usable is the first one. It is used like:
engine.Evaluate("a + b + c", new { a = 1, b = 2, c = 3 });
The new { ... } creates an anonymous object, that is then "unpacked" here through the use of reflection to a Dictionary<string, decimal> to be fed to the private Evaluate().
If you try to use the other notation, the one like:
engine.Evaluate("a + b + c", a: 1, b: 2, c: 3 });
then the .NET can't match the method to the public Evaluate() that is present, but the class, being a subclass of DynamicObject, causes the C# compiler to write some "magic" code that launches this method (that is still implemented by the ExpressionEvaluator):
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
That first checks that we want to call Evaluate:
if (nameof(Evaluate) != binder.Name)
and if we are trying to call Evaluate, it unpacks the parameters to a new Dictionary<string, decimal>() and then calls the private Evaluate().
As a sidenote, to use the "dynamic" way of writing Evaluate you have to declare the engine variable like;
dynamic dynamicEngine = new ExpressionEvaluator();
So using the dynamic variable type.
Now... As the library is written you can:
Use an anonymous object, with the problem that anonymous objects must have their "shape" defined at compile time (so at compile time you must know that you will need a a, a b and a c. You can't need a d at runtime if you didn't create a new { a, b, c, d } at compile time). See for example a response I gave three years ago about how to create dynamic anonymous types at runtime. One of the reasons I gave for that block of code was:
there are parts of the .NET framework that heavily use reflection to render objects (for example all the various datagrids). These parts are incompatible with dynamic objects and often don't support object[]. A solution is often to encapsulate the data in a DataTable... or you can use this :-)
Note that in one of the comments to that response there is a link to a modified version of my code used by one of the many implementations of Dynamic.Linq.
Use a non-anonymous object (a new Foo { a = 1, b = 2 c = 3 }). The library doesn't make distinctions between anonymous and non-anonymous objects. So same limitation as before, because at compile time you need a Foo class with the right number of parameters
Use the dynamic notation. Sadly even that is quite static. You can't easily add new parameters, that for the number and name of the "variables" must be defined at compile time.
A possible solution is to modify the source code (it is a single file) and make public this method:
private decimal Evaluate(string expression, Dictionary<string, decimal> arguments)
then you can easily and dynamically populate the Dictionary<string, decimal> arguments
Take the following:
class A {}
class B : A {}
class C
{
C()
{
var b = new B();
Foo(b);
Foo2(ref b); // <= compile-time error:
// "The 'ref' argument doesn't match the parameter type"
}
void Foo(A a) {}
void Foo2(ref A a) {}
}
Why does the above compile-time error occur? This happens with both ref and out arguments.
=============
UPDATE: I used this answer as the basis for this blog entry:
Why do ref and out parameters not allow type variation?
See the blog page for more commentary on this issue. Thanks for the great question.
=============
Let's suppose you have classes Animal, Mammal, Reptile, Giraffe, Turtle and Tiger, with the obvious subclassing relationships.
Now suppose you have a method void M(ref Mammal m). M can both read and write m.
Can you pass a variable of type Animal to M?
No. That variable could contain a Turtle, but M will assume that it contains only Mammals. A Turtle is not a Mammal.
Conclusion 1: ref parameters cannot be made "bigger". (There are more animals than mammals, so the variable is getting "bigger" because it can contain more things.)
Can you pass a variable of type Giraffe to M?
No. M can write to m, and M might want to write a Tiger into m. Now you've put a Tiger into a variable which is actually of type Giraffe.
Conclusion 2: ref parameters cannot be made "smaller".
Now consider N(out Mammal n).
Can you pass a variable of type Giraffe to N?
No. N can write to n, and N might want to write a Tiger.
Conclusion 3: out parameters cannot be made "smaller".
Can you pass a variable of type Animal to N?
Hmm.
Well, why not? N cannot read from n, it can only write to it, right? You write a Tiger to a variable of type Animal and you're all set, right?
Wrong. The rule is not "N can only write to n".
The rules are, briefly:
1) N has to write to n before N returns normally. (If N throws, all bets are off.)
2) N has to write something to n before it reads something from n.
That permits this sequence of events:
Declare a field x of type Animal.
Pass x as an out parameter to N.
N writes a Tiger into n, which is an alias for x.
On another thread, someone writes a Turtle into x.
N attempts to read the contents of n, and discovers a Turtle in what it thinks is a variable of type Mammal.
Clearly we want to make that illegal.
Conclusion 4: out parameters cannot be made "larger".
Final conclusion: Neither ref nor out parameters may vary their types. To do otherwise is to break verifiable type safety.
If these issues in basic type theory interest you, consider reading my series on how covariance and contravariance work in C# 4.0.
Because in both cases you must be able to assign value to ref/out parameter.
If you try to pass b into Foo2 method as reference, and in Foo2 you try to assing a = new A(), this would be invalid.
Same reason you can't write:
B b = new A();
You're struggling with the classic OOP problem of covariance (and contravariance), see wikipedia: much as this fact may defy intuitive expectations, it's mathematically impossible to allow substitution of derived classes in lieu of base ones for mutable (assignable) arguments (and also containers whose items are assignable, for just the same reason) while still respecting Liskov's principle. Why that is so is sketched in the existing answers, and explored more deeply in these wiki articles and links therefrom.
OOP languages that appear to do so while remaining traditionally statically typesafe are "cheating" (inserting hidden dynamic type checks, or requiring compile-time examination of ALL sources to check); the fundamental choice is: either give up on this covariance and accept practitioners' puzzlement (as C# does here), or move to a dynamic typing approach (as the very first OOP language, Smalltalk, did), or move to immutable (single-assignment) data, like functional languages do (under immutability, you can support covariance, and also avoid other related puzzles such as the fact that you cannot have Square subclass Rectangle in a mutable-data world).
Consider:
class C : A {}
class B : A {}
void Foo2(ref A a) { a = new C(); }
B b = null;
Foo2(ref b);
It would violate type-safety
While the other responses have succinctly explained the reasoning behind this behavior, I think it's worth mentioning that if you really need to do something of this nature you can accomplish similar functionality by making Foo2 into a generic method, as such:
class A {}
class B : A {}
class C
{
C()
{
var b = new B();
Foo(b);
Foo2(ref b); // <= no compile error!
}
void Foo(A a) {}
void Foo2<AType> (ref AType a) where AType: A {}
}
Because giving Foo2 a ref B would result in a malformed object because Foo2 only knows how to fill A part of B.
Isn't that the compiler telling you it would like you to explicitly cast the object so that it can be sure you know what your intentions are?
Foo2(ref (A)b)
Makes sense from a safety perspective, but I would have preferred it if the compiler gave a warning instead of an error, since there are legitimate uses of polymoprhic objects passed by reference. e.g.
class Derp : interfaceX
{
int somevalue=0; //specified that this class contains somevalue by interfaceX
public Derp(int val)
{
somevalue = val;
}
}
void Foo(ref object obj){
int result = (interfaceX)obj.somevalue;
//do stuff to result variable... in my case data access
obj = Activator.CreateInstance(obj.GetType(), result);
}
main()
{
Derp x = new Derp();
Foo(ref Derp);
}
This won't compile, but would it work?
If you use practical examples for your types, you'll see it:
SqlConnection connection = new SqlConnection();
Foo(ref connection);
And now you have your function that takes the ancestor (i.e. Object):
void Foo2(ref Object connection) { }
What can possibly be wrong with that?
void Foo2(ref Object connection)
{
connection = new Bitmap();
}
You just managed to assign a Bitmap to your SqlConnection.
That's no good.
Try again with others:
SqlConnection conn = new SqlConnection();
Foo2(ref conn);
void Foo2(ref DbConnection connection)
{
conn = new OracleConnection();
}
You stuffed an OracleConnection over-top of your SqlConnection.
In my case my function accepted an object and I couldn't send in anything so I simply did
object bla = myVar;
Foo(ref bla);
And that works
My Foo is in VB.NET and it checks for type inside and does a lot of logic
I apologize if my answer is duplicate but others were too long
I saw a lot of code with the following structure:
public void Blah()
{
int a = 0;
string b = "";
DateTime c = DateTime.MinValue;
bool d = false;
// ...More initializations with dummy values
// Overwrite the values in a, b, c, d, e.g. a = ReturnInt();
// Do calculations, reading the values from a, b, c, d, like DoCalculations(a);
}
In general I much prefer something like:
public void Blah()
{
int a = GetInt();
string b = GetString();
DateTime c = GetDateTime();
bool d = GetBool();
// Do calculations, reading the values from a, b, c, d, like DoCalculations(a);
}
Is that really necessary and will there any performance hits due to the extra initializations?
Variables should be initialized before use only if that use is a read if you are going to overwrite it immediately after initialization, it is better to follow the 2nd style you show, mainly for readability purposes, I expect performance hit (from style #1) if any would be typically minimal.
Initializing variables is a common standard used by many developers.
Initializing variables is done because depending on the language and environment, reading uninitialized variables may yield undefined behavior. And because the exact conditions where variables may or may not be initialized automatically is difficult to remember, people tend to simply always initialize objects before using them.
It is generally considered a good practice to perform this initialization in the constructor.
It is also specifically mentioned in Scott Meyers' very popular book Effective C++.
Item 4: Make sure objects are initialized before they're used.
I've seen these two things lately and I'm a bit confused.
var blah = new MyClass() { Name = "hello" }
and
var blah = new MyClass { Name = "hello" }
Whats the difference? and why do they both work?
Update:
Does this mean that if i have something in a constructor which does some computation that i would have to call the first one??
As far as I know, they're exactly equivalent. The C# specification (or at least Microsoft's implementation of it) allows you to omit the () when using the default constructor (no parameters) as long as you're using curly brackets (i.e. the syntax for object initialisers). Note that the object initializer makes no difference to the constructor here - the new MyClass bit still gets interpreted separately as a call to the default constructor. Personally, I would recommend you always include the round brackets () for consistency - you need them when you don't have an object initializer following.
There is no difference, first form just points out that you are also calling the constructor:
class Ö {
public string Ä { get; set; }
public string Å { get; set; }
public Ö() { Å = "dear";}
public Ö(string å) { Å = å; }
}
Console.WriteLine(new Ö { Ä = "hello" }.Å);
Console.WriteLine(new Ö("world") { Ä = "hello" }.Å);
will result in:
dear
world
To add to the above comments, adding extra's definitely help to clarify what constructor or init method is being called. Definitely a styling aspect also....
I guess they retain the () form for object initializers because some users like the clarity of () for invoking the constructor, but iirc, C++ (or the first versions) allow invoking constructor without the parentheses. My second guess, they(language designers) are leaning to make C# have JSON-like structure, which is kinda neat, so they facilitate invoking constructor without the (). I favor the second form.
There's no difference, just like the property(though so bad) of VB.NET would allow you to assign variables in two forms: button1.Height = 100 button1.Height() = 1000 Kinda lame, if you may ask.
Actually they don't have much difference until you deal with Types that don't have default empty constructor. In such a case you can get benefit writing something like "new SomeClass(MandatoryArgument) { Prop1 = 1, Prop2 = 2 }"