Whille creating some dummy data for a collection for a WPF/MVVM project, I produced the following wrong code, which compiles fine, but throws an exception at runtime.
There's a nested structure of data objects, which I wrongly instantiate with only the curly braces (looks like writing JavaScript does cause permanent damage to the brain).
using System.Collections.ObjectModel;
namespace testapp
{
class Program
{
static void Main(string[] args)
{
var collection = new ObservableCollection<TopLevelDataObject>();
collection.Add(new TopLevelDataObject{Nested = {Bar = 5}}); // NullReferenceException
}
class TopLevelDataObject
{
public NestedDataObject Nested { get; set; }
public string Foo { get; set; }
}
class NestedDataObject
{
public double Bar { get; set; }
}
}
}
Why does that compile?
If I create an annonymous type, like Nested = new {Bar = 5}
, I get the error message during compilation (which thus fails):
Cannot implicitly convert type '<anonymous type: int Bar>' to 'testapp.Program.NestedDataObject'
Why do I not get such an error when ommitting the new
operator?
It even gives me a code hint for the property:
My guess would be that {Bar = 5}
is simply a code block, which on its own is a valid thing to have.
But why is it valid to assign a code block to anything (in this case, the Nested
property)?
Why does that compile?
Because when that code is compiled, it is compiled as just a set of assignment operations. It doesn't all have to be new instances you create.
If you construct a new instance of Nested
from the constructor, you can assign a value to Nested.Bar
.
Change public NestedDataObject Nested { get; set; }
to this to see how it works:
public NestedDataObject Nested { get; } = new NestedDataObject();
(Note you can never assign a value to Nested
outside the constructor in the above code!)