It seems that the C# 3.0 object initializer syntax allows one to exclude the open/close pair of parentheses in the constructor when there is a parameterless constructor existing. Example:
var x = new XTypeName { PropA = value, PropB = value };
As opposed to:
var x = new XTypeName() { PropA = value, PropB = value };
I'm curious why the constructor open/close parentheses pair is optional here after XTypeName?
This question was the subject of my blog on September 20th 2010. Josh and Chad's answers ("they add no value so why require them?" and "to eliminate redundancy") are basically correct. To flesh that out a bit more:
The feature of allowing you to elide the argument list as part of the "larger feature" of object initializers met our bar for "sugary" features. Some points we considered:
the design and specification cost was low
we were going to be extensively changing the parser code that handles object creation anyway; the additional development cost of making the parameter list optional was not large compared to the cost of the larger feature
the testing burden was relatively small compared to the cost of the larger feature
the documentation burden was relatively small compared...
the maintenance burden was anticipated to be small; I don't recall any bugs reported in this feature in the years since it shipped.
the feature does not pose any immediately obvious risks to future features in this area. (The last thing we want to do is make a cheap, easy feature now that makes it much harder to implement a more compelling feature in the future.)
the feature adds no new ambiguities to the lexical, grammatical or semantic analysis of the language. It poses no problems for the sort of "partial program" analysis that is performed by the IDE's "IntelliSense" engine while you are typing. And so on.
the feature hits a common "sweet spot" for the larger object initialization feature; typically if you are using an object initializer it is precisely because the constructor of the object does not allow you to set the properties you want. It is very common for such objects to simply be "property bags" that have no parameters in the ctor in the first place.
Why then did you not also make empty parentheses optional in the default constructor call of an object creation expression that does not have an object initializer?
Take another look at that list of criteria above. One of them is that the change does not introduce any new ambiguity in the lexical, grammatical or semantic analysis of a program. Your proposed change does introduce a semantic analysis ambiguity:
class P
{
class B
{
public class M { }
}
class C : B
{
new public void M(){}
}
static void Main()
{
new C().M(); // 1
new C.M(); // 2
}
}
Line 1 creates a new C, calls the default constructor, and then calls the instance method M on the new object. Line 2 creates a new instance of B.M and calls its default constructor. If the parentheses on line 1 were optional then line 2 would be ambiguous. We would then have to come up with a rule resolving the ambiguity; we could not make it an error because that would then be a breaking change that changes an existing legal C# program into a broken program.
Therefore the rule would have to be very complicated: essentially that the parentheses are only optional in cases where they don't introduce ambiguities. We'd have to analyze all the possible cases that introduce ambiguities and then write code in the compiler to detect them.
In that light, go back and look at all the costs I mention. How many of them now become large? Complicated rules have large design, spec, development, testing and documentation costs. Complicated rules are much more likely to cause problems with unexpected interactions with features in the future.
All for what? A tiny customer benefit that adds no new representational power to the language, but does add crazy corner cases just waiting to yell "gotcha" at some poor unsuspecting soul who runs into it. Features like that get cut immediately and put on the "never do this" list.
How did you determine that particular ambiguity?
That one was immediately clear; I am pretty familiar with the rules in C# for determining when a dotted name is expected.
When considering a new feature how do you determine whether it causes any ambiguity? By hand, by formal proof, by machine analysis, what?
All three. Mostly we just look at the spec and noodle on it, as I did above. For example, suppose we wanted to add a new prefix operator to C# called "frob":
x = frob 123 + 456;
(UPDATE: frob is of course await; the analysis here is essentially the analysis that the design team went through when adding await.)
"frob" here is like "new" or "++" - it comes before an expression of some sort. We'd work out the desired precedence and associativity and so on, and then start asking questions like "what if the program already has a type, field, property, event, method, constant, or local called frob?" That would immediately lead to cases like:
frob x = 10;
does that mean "do the frob operation on the result of x = 10, or create a variable of type frob called x and assign 10 to it?" (Or, if frobbing produces a variable, it could be an assignment of 10 to frob x. After all, *x = 10; parses and is legal if x is int*.)
G(frob + x)
Does that mean "frob the result of the unary plus operator on x" or "add expression frob to x"?
And so on. To resolve these ambiguities we might introduce heuristics. When you say "var x = 10;" that's ambiguous; it could mean "infer the type of x" or it could mean "x is of type var". So we have a heuristic: we first attempt to look up a type named var, and only if one does not exist do we infer the type of x.
Or, we might change the syntax so that it is not ambiguous. When they designed C# 2.0 they had this problem:
yield(x);
Does that mean "yield x in an iterator" or "call the yield method with argument x?" By changing it to
yield return(x);
it is now unambiguous.
In the case of optional parens in an object initializer it is straightforward to reason about whether there are ambiguities introduced or not because the number of situations in which it is permissible to introduce something that starts with { is very small. Basically just various statement contexts, statement lambdas, array initializers and that's about it. It's easy to reason through all the cases and show that there's no ambiguity. Making sure the IDE stays efficient is somewhat harder but can be done without too much trouble.
This sort of fiddling around with the spec usually is sufficient. If it is a particularly tricky feature then we pull out heavier tools. For example, when designing LINQ, one of the compiler guys and one of the IDE guys who both have a background in parser theory built themselves a parser generator that could analyze grammars looking for ambiguities, and then fed proposed C# grammars for query comprehensions into it; doing so found many cases where queries were ambiguous.
Or, when we did advanced type inference on lambdas in C# 3.0 we wrote up our proposals and then sent them over the pond to Microsoft Research in Cambridge where the languages team there was good enough to work up a formal proof that the type inference proposal was theoretically sound.
Are there ambiguities in C# today?
Sure.
G(F<A, B>(0))
In C# 1 it is clear what that means. It's the same as:
G( (F<A), (B>0) )
That is, it calls G with two arguments that are bools. In C# 2, that could mean what it meant in C# 1, but it could also mean "pass 0 to the generic method F that takes type parameters A and B, and then pass the result of F to G". We added a complicated heuristic to the parser which determines which of the two cases you probably meant.
Similarly, casts are ambiguous even in C# 1.0:
G((T)-x)
Is that "cast -x to T" or "subtract x from T"? Again, we have a heuristic that makes a good guess.
Because that's how the language was specified. They add no value, so why include them?
It's also very similar to implicity typed arrays
var a = new[] { 1, 10, 100, 1000 }; // int[]
var b = new[] { 1, 1.5, 2, 2.5 }; // double[]
var c = new[] { "hello", null, "world" }; // string[]
var d = new[] { 1, "one", 2, "two" }; // Error
Reference: http://msdn.microsoft.com/en-us/library/ms364047%28VS.80%29.aspx
This was done to simplify the construction of objects. The language designers have not (to my knowledge) specifically said why they felt that this was useful, though it is explicitly mentioned in the C# Version 3.0 Specification page:
An object creation expression can omit the constructor argument list and enclosing parentheses, provided it includes an object or collection initializer. Omitting the constructor argument list and enclosing parentheses is equivalent to specifying an empty argument list.
I suppose that they felt the parenthesis, in this instance, were not necessary in order to show developer intent, since the object initializer shows the intent to construct and set the properties of the object instead.
In your first example, the compiler infers that you're calling the default constructor (the C# 3.0 Language Specification states that if no parenthesis are provided, the default constructor is called).
In the second, you explicitly call the default constructor.
You can also use that syntax to set properties while explicitly passing values to the constructor. If you had the following class definition:
public class SomeTest
{
public string Value { get; private set; }
public string AnotherValue { get; set; }
public string YetAnotherValue { get; set;}
public SomeTest() { }
public SomeTest(string value)
{
Value = value;
}
}
All three statements are valid:
var obj = new SomeTest { AnotherValue = "Hello", YetAnotherValue = "World" };
var obj = new SomeTest() { AnotherValue = "Hello", YetAnotherValue = "World"};
var obj = new SomeTest("Hello") { AnotherValue = "World", YetAnotherValue = "!"};
I am no Eric Lippert, so I can't say for sure, but I would assume it is because the empty parenthesis is not needed by the compiler in order to infer the initialization construct. Therefore it becomes redundant information, and not needed.
Related
Visual Studio is able to warn a user when certain type casts are impossible such as below
public class A{}
public class B{}
// ...
var x = new A();
// example 1
var y = (B)A; // Compiler Error CS0030
// example 2
if(x is B) // Compiler warning CS0184
I have looked but I cannot find any similar compile time checks available for the LINQ OfType<T> operator.
public class A{}
public class B{}
// ...
var x = new List<A>();
var y = x.OfType<B>(); // NO problem
Does anyone know if there is something already existing or would this need to be implemented as a custom compiler warning?
This is not possible as a general solution (a custom analyzer can be written for specific cases though, such as your OfType example).
It's also not necessary though. The compiler error in your first example prevents a runtime InvalidCastException, and in your second example the warning indicates a predicate that's always false, and therefore any code in that if statement is unreachable - usually not the intent.
The OfType call has no possibility of a runtime failure. While there may be a minor performance benefit in your OfType example (as the check will invariably return an empty enumeration), since LINQ is lazily evaluated, the real performance benefit would be very minor, if any; but the requirement for the compiler to understand the method's innner workings to accomplish such task, is ...insanely hard to implement correctly! Compilers, even really advanced ones today, haven't learned to do that.
So, not possible, but that might be ok.
When trying to assign a type to a property of type System.Type, why can't we do this?
foo.NetType = bool;
The compiler produces this warning:
"Expression expected."
The way to solve it is by doing this:
foo.NetType = typeof(bool);
My question is why can't we use the first approach? Isn't the compiler smart enough to figure out what we're trying to accomplish here? Is there some reason why we have to go with the second approach (typeof)?
Good question -- insofar as it is an interesting question in language design. This is maybe not an ideal question for this site, as it is not about specific, actual code.
It would be perfectly feasible to design a language in which a type name may be used as an expression without an explicit typeof operator.
Doing so would require a small number of extra rules and clarifications to be added to the language. For example, suppose we had:
enum Color { Red }
class Square
{
Color Color { get; set; }
void M()
{
Type t = Color.GetType();
In C# today this unambiguously means invoke the getter for property Color and call GetType on the result. (See the specification's "Color Color rule" section for an explanation of why.) In your proposed world there are three things this could mean:
Invoke the getter for Color, call GetType on the result, assign the Type object for Color to t.
Color results in a Type object for the type Color. Call GetType on that type, and assign the Type object for System.Type to t.
Color refers to the type Color, GetType refers to the non-static method, and this is an error because this is a static call to a non-static member.
You'd want to clarify the specification so that it was clear when Color in an expression meant the type and when it meant make a type object. So the proposed feature adds a small amount of ambiguity that must be dealt with, but it's totally doable. The language designers could come up with reasonable rules.
A language which allows a language element that is normally part of the compile-time analysis to instead be interpreted as code that creates an object that can be manipulated by code in the same program is called a homoiconic language. C# was a very nonhomoiconic language before C# 3; expression trees made C# much more homoiconic. C# 3 allow lambdas to be treated as program elements that are then used to generate methods that perform the action of the lambda body, but it also supports a homoiconic transformation from the lambda into an object that represents the body of the lambda.
One of the most homoiconic languages is Lisp; Lisp manipulates lists and any Lisp program can itself be though of as a list; it can be quoted and manipulated at runtime as objects rather than as code. So once again we see here the truth of the old joke about language design: every language designer eventually re-invents Lisp, badly.
I digress. Your question then is essentially: should C# be more or less homoiconic with respect to type names? Should a type name have one meaning -- a compile-time directive -- in contexts like
Foo x = new Foo();
object o = new List<Foo>[] {};
Foo.StaticMethod();
and have a very different meaning -- as the construction of an object that can be inspected at runtime in other contexts:
object t = Foo; // Assign a Type object to t.
?
Though it would certainly be possible to design a language like that, I don't much like it. Without an operator in there clearly calling out "hey, we are using what is normally a compile-time element in a homoiconic manner", it's potentially confusing. Before C# 3, there were no other homoiconic language features and so it would seem a bit strange to have the only one be that types could be used as both types or expressions that result in a Type object. And it does seem quite unfortunate that in some expressions it is unclear whether a particular simple name means "I'm using this type at compile time" or "I want to make an object".
Having an explicit typeof operator mitigates all these concerns; it is unambiguous when the type is being used homoiconically and very clear to the reader.
To address a very specific point about your question:
When trying to assign a type to a property of type System.Type...
C# does not generally speaking have special rules that apply only in assignments. The meaning of an expression is usually determined without appealing to the context in which the expression is being used. When we say:
x = y;
We don't generally say "Oh, I know that y is being assigned to x and x is of type X so I'm going to use that information in the analysis of y". Rather, the analysis goes from inside to outside: we work out what y means, and then decide whether or not it is compatible with X.
The exception to this rule is of course lambdas; lambdas do take into account their "target" type because the target type can be used to infer the types of an implicitly typed lambda. Getting these rules right was very complicated.
More generally, it's a bad idea to make assignment expressions special. There are lots of ways that values get assigned to variables:
M(x); // x is assigned to a formal
q = new [] { x }; // x is assigned to the first element of an array
y = new Y() { X = x }; // x is assigned to a property of Y.
You want the rules for all those assignments to be consistent; if an expression means "I'm a type object" then it should mean that in every context in which that expression can appear, not just as the right hand side of an assignment.
Sorry, I misunderstood your goal at first. However, you're still a bit confused.
You're attempting to assign an instance of a Type object to a property. bool is not an instance of the Type class, it is its own type. I appreciate that the terminology is a bit confusing, but they are two different things. That's why it doesn't work.
So here's a SWAG:
If I have a class:
public class Foo
{
public static int Bar = 1;
}
And I have some code like:
var foo = Foo;
You might say "ok, that definitely means the type"
Now if I have something like:
public class Bar
{
public void Foo ()
{
var hmm = Foo;
}
}
What do I mean? The type Foo? The method Foo? The namespace (if it existed) Foo?
By wrapping it in typeof, we make it explicit what we want. Also, it generates specific IL, but I'm assuming your question implicitly means "Why isn't the compiler smarter?"
I have an implementation of DynamicDictionary where all of the entries in the dictionary are of a known type:
public class FooClass
{
public void SomeMethod()
{
}
}
dynamic dictionary = new DynamicDictionary<FooClass>();
dictionary.foo = new FooClass();
dictionary.foo2 = new FooClass();
dictionary.foo3 = DateTime.Now; <--throws exception since DateTime is not FooClass
What I'd like is to be able to have Visual Studio Intellisense work when referencing a method of one of the dictionary entries:
dictionary.foo.SomeMethod() <--would like SomeMethod to pop up in intellisense
The only way I've found to do this is:
((FooClass)dictionary.foo).SomeMethod()
Can anyone recommend a more elegant syntax? I'm comfortable writing a custom implementation of DynamicDictionary with IDynamicMetaObjectProvider.
UPDATE:
Some have asked why dynamics and what my specific problem is. I have a system that lets me do something like this:
UI.Map<Foo>().Action<int, object>(x => x.SomeMethodWithParameters).Validate((parameters) =>
{
//do some method validation on the parameters
return true; //return true for now
}).WithMessage("The parameters are not valid");
In this case the method SomeMethodWithParameters has the signature
public void SomeMethodWithParameters(int index, object target)
{
}
What I have right now for registering validation for individual parameters looks like this:
UI.Map<Foo>().Action<int, object>(x => x.SomeMethodWithParameters).GetParameter("index").Validate((val) =>
{
return true; //valid
}).WithMessage("index is not valid");
What I'd like it to be is:
UI.Map<Foo>().Action<int, object(x => x.SomeMethodWithParameters).index.Validate((val) =>
{
return true;
}).WithMessage("index is not valid");
This works using dynamics, but you lose intellisense after the reference to index - which is fine for now. The question is is there a clever syntactical way (other than the ones metioned above) to get Visual Studio to recognize the type somehow. Sounds so far like the answer is "no".
It seems to me that if there was a generic version of IDynamicMetaObjectProvider,
IDynamicMetaObjectProvider<T>
this could be made to work. But there isn't, hence the question.
In order to get intellisense, you're going to have to cast something to a value that is not dynamic at some point. If you find yourself doing this a lot, you can use helper methods to ease the pain somewhat:
GetFoo(dictionary.Foo).SomeMethod();
But that isn't much of an improvement over what you've got already. The only other way to get intellisense would be to cast the value back to a non-dynamic type or avoid dynamic in the first place.
If you want to use Intellisense, it's usually best to avoid using dynamic in the first place.
typedDictionary["foo"].SomeMethod();
Your example makes it seem likely that you have specific expectations about the structure of your dynamic object. Consider whether there's a way to create a static class structure that would fulfill your needs.
Update
In response to your update: If you don't want to drastically change your syntax, I'd suggest using an indexer so that your syntax can look like this:
UI.Map<Foo>().Action<int, object>(x => x.SomeMethodWithParameters)["index"].Validate((val) => {...});
Here's my reasoning:
You only add four characters (and subtract one) compared to the dynamic approach.
Let's face it: you are using a "magic string." By requiring an actual string, this fact will be immediately obvious to programmers who look at this code. Using the dynamic approach, there's nothing to indicate that "index" is not a known value from the compiler's perspective.
If you're willing to change things around quite a bit, you may want to investigate the way Moq plays with expressions in their syntax, particularly the It.IsAny<T>() method. It seems like you might be able to do something more along these lines:
UI.Map<Foo>().Action(
(x, v) => x.SomeMethodWithParameters(
v.Validate<int>(index => {return index > 1;})
.WithMessage("index is not valid"),
v.AlwaysValid<object>()));
Unlike your current solution:
This wouldn't break if you ended up changing the names of the parameters in the method signature: Just like the compiler, the framework would pay more attention to the location and types of the parameters than to their names.
Any changes to the method signature would cause an immediate flag from the compiler, rather than a runtime exception when the code runs.
Another syntax that's probably slightly easier to accomplish (since it wouldn't require parsing expression trees) might be:
UI.Map<Foo>().Action((x, v) => x.SomeMethodWithParameters)
.Validate(v => new{
index = v.ByMethod<int>(i => {return i > 1;}),
target = v.IsNotNull()});
This doesn't give you the advantages listed above, but it still gives you type safety (and therefore intellisense). Pick your poison.
Aside from Explict Cast,
((FooClass)dictionary.foo).SomeMethod();
or Safe Cast,
(dictionary.foo as FooClass).SomeMethod();
the only other way to switch back to static invocation (which will allow intellisense to work) is to do Implicit Cast:
FooClass foo = dictionary.foo;
foo.SomeMethod().
Declared casting is your only option, can't use helper methods because they will be dynamically invoked giving you the same problem.
Update:
Not sure if this is more elegant but doesn't involve casting a bunch and gets intellisense outside of the lambda:
public class DynamicDictionary<T>:IDynamicMetaObjectProvider{
...
public T Get(Func<dynamic,dynamic> arg){
return arg(this);
}
public void Set(Action<dynamic> arg){
arg(this);
}
}
...
var dictionary = new DynamicDictionary<FooClass>();
dictionary.Set(d=>d.Foo = new FooClass());
dictionary.Get(d=>d.Foo).SomeMethod();
As has already been said (in the question and StriplingWarrior answer) the C# 4 dynamic type does not provide intellisense support. This answer is provided merely to provide an explanation why (based on my understanding).
dynamic to the C# compiler is nothing more than object which has only limited knowledge at compile-time which members it supports. The difference is, at run-time, dynamic attempts to resolve members called against its instances against the type for which the instance it represents knows (providing a form of late binding).
Consider the following:
dynamic v = 0;
v += 1;
Console.WriteLine("First: {0}", v);
// ---
v = "Hello";
v += " World";
Console.WriteLine("Second: {0}", v);
In this snippet, v represents both an instance of Int32 (as seen in the first section of code) and an instance of String in the latter. The use of the += operator actually differs between the two different calls to it because the types involved are inferred at run-time (meaning the compiler doesn't understand or infer usage of the types at compile-time).
Now consider a slight variation:
dynamic v;
if (DateTime.Now.Second % 2 == 0)
v = 0;
else
v = "Hello";
v += 1;
Console.WriteLine("{0}", v);
In this example, v could potentially be either an Int32 or a String depending on the time at which the code is run. An extreme example, I know, though it clearly illustrates the problem.
Considering a single dynamic variable could potentially represent any number of types at run-time, it would be nearly impossible for the compiler or IDE to make assumptions about the types it represents prior to it's execution, so Design- or Compile-time resolution of a dynamic variable's potential members is unreasonable (if not impossible).
It seems that the C# 3.0 object initializer syntax allows one to exclude the open/close pair of parentheses in the constructor when there is a parameterless constructor existing. Example:
var x = new XTypeName { PropA = value, PropB = value };
As opposed to:
var x = new XTypeName() { PropA = value, PropB = value };
I'm curious why the constructor open/close parentheses pair is optional here after XTypeName?
This question was the subject of my blog on September 20th 2010. Josh and Chad's answers ("they add no value so why require them?" and "to eliminate redundancy") are basically correct. To flesh that out a bit more:
The feature of allowing you to elide the argument list as part of the "larger feature" of object initializers met our bar for "sugary" features. Some points we considered:
the design and specification cost was low
we were going to be extensively changing the parser code that handles object creation anyway; the additional development cost of making the parameter list optional was not large compared to the cost of the larger feature
the testing burden was relatively small compared to the cost of the larger feature
the documentation burden was relatively small compared...
the maintenance burden was anticipated to be small; I don't recall any bugs reported in this feature in the years since it shipped.
the feature does not pose any immediately obvious risks to future features in this area. (The last thing we want to do is make a cheap, easy feature now that makes it much harder to implement a more compelling feature in the future.)
the feature adds no new ambiguities to the lexical, grammatical or semantic analysis of the language. It poses no problems for the sort of "partial program" analysis that is performed by the IDE's "IntelliSense" engine while you are typing. And so on.
the feature hits a common "sweet spot" for the larger object initialization feature; typically if you are using an object initializer it is precisely because the constructor of the object does not allow you to set the properties you want. It is very common for such objects to simply be "property bags" that have no parameters in the ctor in the first place.
Why then did you not also make empty parentheses optional in the default constructor call of an object creation expression that does not have an object initializer?
Take another look at that list of criteria above. One of them is that the change does not introduce any new ambiguity in the lexical, grammatical or semantic analysis of a program. Your proposed change does introduce a semantic analysis ambiguity:
class P
{
class B
{
public class M { }
}
class C : B
{
new public void M(){}
}
static void Main()
{
new C().M(); // 1
new C.M(); // 2
}
}
Line 1 creates a new C, calls the default constructor, and then calls the instance method M on the new object. Line 2 creates a new instance of B.M and calls its default constructor. If the parentheses on line 1 were optional then line 2 would be ambiguous. We would then have to come up with a rule resolving the ambiguity; we could not make it an error because that would then be a breaking change that changes an existing legal C# program into a broken program.
Therefore the rule would have to be very complicated: essentially that the parentheses are only optional in cases where they don't introduce ambiguities. We'd have to analyze all the possible cases that introduce ambiguities and then write code in the compiler to detect them.
In that light, go back and look at all the costs I mention. How many of them now become large? Complicated rules have large design, spec, development, testing and documentation costs. Complicated rules are much more likely to cause problems with unexpected interactions with features in the future.
All for what? A tiny customer benefit that adds no new representational power to the language, but does add crazy corner cases just waiting to yell "gotcha" at some poor unsuspecting soul who runs into it. Features like that get cut immediately and put on the "never do this" list.
How did you determine that particular ambiguity?
That one was immediately clear; I am pretty familiar with the rules in C# for determining when a dotted name is expected.
When considering a new feature how do you determine whether it causes any ambiguity? By hand, by formal proof, by machine analysis, what?
All three. Mostly we just look at the spec and noodle on it, as I did above. For example, suppose we wanted to add a new prefix operator to C# called "frob":
x = frob 123 + 456;
(UPDATE: frob is of course await; the analysis here is essentially the analysis that the design team went through when adding await.)
"frob" here is like "new" or "++" - it comes before an expression of some sort. We'd work out the desired precedence and associativity and so on, and then start asking questions like "what if the program already has a type, field, property, event, method, constant, or local called frob?" That would immediately lead to cases like:
frob x = 10;
does that mean "do the frob operation on the result of x = 10, or create a variable of type frob called x and assign 10 to it?" (Or, if frobbing produces a variable, it could be an assignment of 10 to frob x. After all, *x = 10; parses and is legal if x is int*.)
G(frob + x)
Does that mean "frob the result of the unary plus operator on x" or "add expression frob to x"?
And so on. To resolve these ambiguities we might introduce heuristics. When you say "var x = 10;" that's ambiguous; it could mean "infer the type of x" or it could mean "x is of type var". So we have a heuristic: we first attempt to look up a type named var, and only if one does not exist do we infer the type of x.
Or, we might change the syntax so that it is not ambiguous. When they designed C# 2.0 they had this problem:
yield(x);
Does that mean "yield x in an iterator" or "call the yield method with argument x?" By changing it to
yield return(x);
it is now unambiguous.
In the case of optional parens in an object initializer it is straightforward to reason about whether there are ambiguities introduced or not because the number of situations in which it is permissible to introduce something that starts with { is very small. Basically just various statement contexts, statement lambdas, array initializers and that's about it. It's easy to reason through all the cases and show that there's no ambiguity. Making sure the IDE stays efficient is somewhat harder but can be done without too much trouble.
This sort of fiddling around with the spec usually is sufficient. If it is a particularly tricky feature then we pull out heavier tools. For example, when designing LINQ, one of the compiler guys and one of the IDE guys who both have a background in parser theory built themselves a parser generator that could analyze grammars looking for ambiguities, and then fed proposed C# grammars for query comprehensions into it; doing so found many cases where queries were ambiguous.
Or, when we did advanced type inference on lambdas in C# 3.0 we wrote up our proposals and then sent them over the pond to Microsoft Research in Cambridge where the languages team there was good enough to work up a formal proof that the type inference proposal was theoretically sound.
Are there ambiguities in C# today?
Sure.
G(F<A, B>(0))
In C# 1 it is clear what that means. It's the same as:
G( (F<A), (B>0) )
That is, it calls G with two arguments that are bools. In C# 2, that could mean what it meant in C# 1, but it could also mean "pass 0 to the generic method F that takes type parameters A and B, and then pass the result of F to G". We added a complicated heuristic to the parser which determines which of the two cases you probably meant.
Similarly, casts are ambiguous even in C# 1.0:
G((T)-x)
Is that "cast -x to T" or "subtract x from T"? Again, we have a heuristic that makes a good guess.
Because that's how the language was specified. They add no value, so why include them?
It's also very similar to implicity typed arrays
var a = new[] { 1, 10, 100, 1000 }; // int[]
var b = new[] { 1, 1.5, 2, 2.5 }; // double[]
var c = new[] { "hello", null, "world" }; // string[]
var d = new[] { 1, "one", 2, "two" }; // Error
Reference: http://msdn.microsoft.com/en-us/library/ms364047%28VS.80%29.aspx
This was done to simplify the construction of objects. The language designers have not (to my knowledge) specifically said why they felt that this was useful, though it is explicitly mentioned in the C# Version 3.0 Specification page:
An object creation expression can omit the constructor argument list and enclosing parentheses, provided it includes an object or collection initializer. Omitting the constructor argument list and enclosing parentheses is equivalent to specifying an empty argument list.
I suppose that they felt the parenthesis, in this instance, were not necessary in order to show developer intent, since the object initializer shows the intent to construct and set the properties of the object instead.
In your first example, the compiler infers that you're calling the default constructor (the C# 3.0 Language Specification states that if no parenthesis are provided, the default constructor is called).
In the second, you explicitly call the default constructor.
You can also use that syntax to set properties while explicitly passing values to the constructor. If you had the following class definition:
public class SomeTest
{
public string Value { get; private set; }
public string AnotherValue { get; set; }
public string YetAnotherValue { get; set;}
public SomeTest() { }
public SomeTest(string value)
{
Value = value;
}
}
All three statements are valid:
var obj = new SomeTest { AnotherValue = "Hello", YetAnotherValue = "World" };
var obj = new SomeTest() { AnotherValue = "Hello", YetAnotherValue = "World"};
var obj = new SomeTest("Hello") { AnotherValue = "World", YetAnotherValue = "!"};
I am no Eric Lippert, so I can't say for sure, but I would assume it is because the empty parenthesis is not needed by the compiler in order to infer the initialization construct. Therefore it becomes redundant information, and not needed.
Hi I use initializer block in C#
new Something { foo = 1, bar = 2 };
but people say this is bad practice.
I don't think it is wrong, is it?
You need to ask yourself whether your type should be mutable or not. Personally, I like immutable types - they make it easier to reason about what's going on, easier to validate (once the constructor has been called and the state validated, you know it's not going to become invalid) and they're great for concurrency.
On the other hand, object initializers are certainly useful in cases where it is reasonable to have mutable types. As an example, ProcessStartInfo is effectively used as a builder type for Process. It's useful to be able to write:
var info = new ProcessStartInfo {
FileName = "notepad.exe",
Arguments = "foo.txt",
ErrorDialog = true
};
Process process = Process.Start(info);
Indeed, you can even do all this inline instead of having an extra variable. My Protocol Buffers port uses the same sort of pattern:
Foo foo = new Foo.Builder {
FirstProperty = "first",
SecondProperty = "second"
}.Build();
Now one alternative to the builder pattern is constructor parameters (possibly via factory methods). The historical downside of this is that you needed different overloads depending on which properties were being set, and if several parameters had the same type it could be hard to tell which was which. C# 4 makes this significantly easier using optional parameters and named arguments. For example, if you're building an email class you could have:
Email email = new Email(
from: "skeet#pobox.com",
to: "jon#example.com",
subject: "Test email",
body: textVariable
);
This has many of the same benefits of object initializers in terms of clarity, but without the mutability penalty. The constructor call above may have missed out some optional parameters such as attachments and a BCC list. I think this will prove to be one of the biggest benefits of C# 4 for those of us who like immutability but also like the clarity of object initializers.
It's questionable (I won't say "bad") practice to use initialization blocks as a substitute for the appropriate constructor overload, if one exists.
public class Entity
{
public Entity()
{
}
public Entity(int id, string name)
{
this.ID = id;
this.Name = name;
}
public int ID { get; set; }
public string Name { get; set; }
}
If you have this very simple class, then it is generally preferable to write:
var entity = new Entity(1, "Fred");
...than it is to write:
var entity = new Entity { ID = 1, Name = "Fred" };
There are at least two good reasons for this:
You don't know exactly what the constructor is doing. It's possible that, in some circumstances, it might be significantly more expensive to construct the object and then set public properties vs. passing the values through the constructor itself. (You may know that this is not the case, but as the consumer of a class, you shouldn't presume to know care about the implementation details, because they are subject to change).
Your code won't break if one or more of those properties have their names changed, or become read-only (which the ID probably should have been in the first place, but perhaps wasn't due to architectural constraints like that of an ORM).
However, there is one case where you have to use initializers instead of overloaded constructors, and that is when chaining selects in a Linq to SQL/EF query:
var bars =
from f in ctx.Foo
select new Bar { X = f.X, Y = f.Y };
var bazzes =
from b in bars
select new Baz { ... };
This can actually fail with a "no supported mapping" if you use constructor overloads instead of default constructors + initializers. This is, however, a constraint of the technology being used (and an undesirable one at that), and not a coding style issue.
In other cases, you should prefer the constructor overload over the initializer.
If there is no useful/relevant constructor overload that can do the same thing as your initializer, then go ahead and write the initializer, there's nothing wrong with it. The feature exists for a good reason - it makes the code easier to write and read.
but people say is bad practice.
Who says this? At the very least, that’s a controversial statement.
It seems to be all the rage at the moment, and many prominent C# blogs use it extensively.
The advantage over using a constructor is that it’s more readable since the code clearly shows which properties get assigned what values. Compare:
var x = new Something { Foo = 1, Bar = 2 };
with
var x = new Something(1, 2);
Furthermore, if no appropriate constructor is present, the code is more concise than manually assigning to properties:
var x = new Something();
x.Foo = 1;
x.Bar = 2;
Personally, I prefer immutable objects (i.e. objects that, once created, cannot be changed). Unfortunately, the initializer blocks cannot be used in conjunction with such objects (at the moment) because to make this pattern work the object has to have property setters, which an immutable object doesn’t have.
But as long as the object used isn’t immutable I don’t see a compelling reason against using the initializer notation.
Initializer blocks are GREAT practice for the following reasons:
You get to create an object and override its properties before getting its reference
this.ObjA = new ObjA
{
Age = 20,
Name = "123",
};
// this.ObjA will not be set until properties have all been defined
// - safer when multithreading
The parameter-less constructor can still do things behind the scene
(e.g. initialize state members).
You can use in conjunction with constructors with parameters
this.ObjA = new ObjA(20)
{
Name = "123",
};
Using parameter-less constructors is better for (de)serializing scenarios
You can create various objects, change their state via GUI, serialize them, deserialize them elsewhere.
This practice forces authors to write more robust code - where the order in which things are done is less lightly to cause the application to crash every time the class's metadata is changed.
There is nothing wrong with initializer blocks, but if your type for example has many properties, and only a couple of them need to be set on every instance, then you should make them required in a constructor.
The user of your class will know that they can't create an object without specifying those values.
The properties that are essential for the object work, should be initialized in the constructor, so you should provide the appropiate parameters in hthe contstructor.
Initializer blocks are very handy for several of the new features of C# 3.0, but you should keep in mind, that they are not here for replace the parameters in the constructor.
I think it's good.
Because it reduces your typing a lot