让我们说:
class Foo
{
public int IntPropertyInFoo { get; set; }
public Bar BarPropertyInA { get; set; }
}
class Bar
{
public string StringPropertyInBar { get; set; }
}
然后我们想用对象初始值设定项实例化Foo
:
public static void Main(string[] args)
{
var foo = new Foo
{
IntPropertyInFoo = 123,
BarPropertyInA = // Ommiting new and type name - why does it compile?
{
StringPropertyInBar = "something"
}
};
}
初始化BarPropertyInA
的语法让我感到困惑,因为代码在没有警告的情况下编译,并且在运行时抛出NullReferenceException
。我没有认识到这种语法,但是当它与字段一起使用时,它似乎具有相同的效果,而不是属性。
反汇编已编译的代码会产生以下结果:
.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
看起来像:
public static void Main(string[] args)
{
var foo = new Foo
{
IntPropertyInFoo = 123
};
foo.BarPropertyInA.StringPropertyInBar = "something";
}
如果属性/字段在构造函数中初始化,那么这应该是初始化属性&field的成员的一些语法糖吗?
答案 0 :(得分:2)
是的,它是一种初始化属性的简写,这些属性从空开始而不是空。 .net集合属性就是一个很好的例子。
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"
};
它还允许您初始化只读属性的值。
//compiles and works
var message = new MailMessage { To = { "test@stackoverflow.com" } };
message = new MailMessage
{
// won't compile: To is read-only
To = new MailAddressCollection { "test@stackoverflow.com" },
};
从这篇文章中逐字借词: http://www.codeducky.org/even-concise-c-object-initializers/
New-less初始化程序语法允许您使代码更简洁,并使用初始化语法来配置只读属性。实际上,由于大多数基类库和流行的.NET包类遵循集合属性的空的空模式,因此几乎总能利用新的语法。最后,使用new-less初始化还意味着您可以通过保留对象初始化的任何默认值而受益。