I was working on one of our new applications when I made a stupid mistake… I forgot to write: ”new ClassName” inside an object initializer. Strangely VS just compiled the code… without any error or warning. (I’ve used VS 2015, .Net 4.5.2)
My Code:
var target = new MyClass
{
MyValues = new List<MyOtherClass>
{
new MyOtherClass
{
Start = new DateTimeValue
{
DateTime = new DateTime(2015, 08, 23)
},
End = {
DateTime = new DateTime(2015, 08, 23)
}
}
}
};
(Start and End are both of type DateTimeValue)
When I start the application, this code has thrown a NullReferenceException. (Adding “new DateTimeValue” fixed the problem). Why was there no error from the compiler?
There's nothing wrong there at all. It's using an object initializer for End
which sets properties using the existing value instead of assigning a new value to End
. Your code is equivalent to:
var tmp0 = new MyClass();
var tmp1 = new List<MyOtherClass>();
var tmp2 = new MyOtherClass();
var tmp3 = new DateTimeValue();
tmp3.DateTime = new DateTime(2015, 8, 23);
// Note the assignment to Start here
tmp2.Start = tmp3;
// No assignment to End -
// it's calling the End "getter" and then the DateTime "setter" on the result
tmp2.End.DateTime = new DateTime(2015, 8, 23);
tmp1.Add(tmp2);
tmp0.MyValues = tmp1;
var target = tmp0;
From the C# 5 specification, section 7.6.10.2:
A member initializer that specifies an object initializer after the equals sign is a nested object initializer, i.e. an initialization of an embedded object. Instead of assigning a new value to the field or property, the assignments in the nested object initializer are treated as assignments to members of the field or property.
That's exactly what you're doing here - the { DateTime = ... }
part is an object initializer.
See more on this question at Stackoverflow