无法识别的C#语法
假设我们有:无法识别的C#语法,c#,.net,C#,.net,假设我们有: 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
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";
}
如果属性/字段是在构造函数中初始化的,那么这应该是初始化属性/字段成员的一些语法糖吗?是的,它是初始化以空而不是空开头的属性的一种缩写。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" },
};
从这篇文章中借用了几乎一字不差的内容:
新的less初始值设定项语法允许您使代码更加简洁,并使用初始化语法配置只读属性。事实上,由于大多数基类库和流行的.NET包类都遵循集合属性的空对空模式,因此您几乎总能利用新的less语法。最后,使用newless初始化还意味着您可以保留初始化对象时使用的默认值
这就是为什么我总是在我的类构造函数中新建其他类和列表。如果你有一个
Foo
的构造函数,它将BarPropertyInA
设置为一个新的Bar
,那么这就允许你只设置StringPropertyInBar
属性。他们使用了这个,而不是类似于BarPropertyInA.StringPropertyInBar=“something”
的东西,我相信数组构造函数和类似的东西也是如此。Net将暗示基于InstanceInit上下文的最佳构造函数似乎答案是肯定的。