Let's say we have:
class Foo
{
public int IntPropertyInFoo { get; set; }
public Bar BarPropertyInA { get; set; }
}
class Bar
{
public string StringPropertyInBar { get; set; }
}
Then we'd like to instantiate Foo
with an object initializer:
public static void Main(string[] args)
{
var foo = new Foo
{
IntPropertyInFoo = 123,
BarPropertyInA = // Ommiting new and type name - why does it compile?
{
StringPropertyInBar = "something"
}
};
}
The syntax of initializing BarPropertyInA
baffles me, because the code compiles without warnings and, when run, throws NullReferenceException
. I don't recognize that syntax, but it seems to have the same effect when used with a field, rather than a property.
Disassembling the compiled code yields this:
.method public hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 34 (0x22)
.maxstack 3
.locals init ([0] class Test.Foo foo)
IL_0000: nop
IL_0001: newobj instance void Test.Foo::.ctor()
IL_0006: dup
IL_0007: ldc.i4.s 123
IL_0009: callvirt instance void Test.Foo::set_IntPropertyInFoo(int32)
IL_000e: nop
IL_000f: dup
IL_0010: callvirt instance class Test.Bar Test.Foo::get_BarPropertyInA()
IL_0015: ldstr "something"
IL_001a: callvirt instance void Test.Bar::set_StringPropertyInBar(string)
IL_001f: nop
IL_0020: stloc.0
IL_0021: ret
} // end of method Program::Main
Which looks like:
public static void Main(string[] args)
{
var foo = new Foo
{
IntPropertyInFoo = 123
};
foo.BarPropertyInA.StringPropertyInBar = "something";
}
So is this supposed to be some syntactic sugar for initializing property's/field's members, provided that the property/field is initialized in the constructor?
Yes, it is a sort of shorthand for initializing properties that start as empty rather than null. The .net collection properties are a good example of this.
var cmd = new System.Data.SqlClient.SqlCommand()
{
Parameters =
{
new System.Data.SqlClient.SqlParameter() { ParameterName = "@p1", Value = "SomValue"}
},
CommandText = "select 1 from Table1 where Value = @p1"
};
It also allows you to initialize the values of read-only properties.
//compiles and works
var message = new MailMessage { To = { "[email protected]" } };
message = new MailMessage
{
// won't compile: To is read-only
To = new MailAddressCollection { "[email protected]" },
};
Borrowed pretty much verbatim from this article: http://www.codeducky.org/even-concise-c-object-initializers/
New-less initializer syntax allows you to make your code a bit more concise and to use initialization syntax for configuring read-only properties. Indeed, since most base class library and popular .NET package classes follow the empty over null pattern for collection properties, you can nearly always take advantage of new-less syntax for them. Finally, using new-less initialization also means that you benefit from leaving in place any defaults an object was initialized with.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With