我最近在C#中学习了对象初始化程序,但现在我想知道它在与构造函数冲突时是如何工作的。
public class A
{
public bool foo { get; set; }
public A()
{
foo = true;
}
public A(bool bar)
{
foo = bar;
}
}
当我尝试这种情况会发生什么?
public class B
{
a = A() {foo = false};
b = A(true) {foo = false};
}
构造函数中的默认值是让bool
开始为真并且可以更改的好方法吗?
public A(bar=true)
{
foo = bar;
}
答案 0 :(得分:43)
编译器首先访问对象初始化器 默认实例构造函数,然后处理该成员 初始化。
这意味着在最简单的情况下(命名对象初始化),它基本上是简写(或语法糖),用于调用默认构造函数然后调用属性setter(s)。在匿名类型的情况下,实际上需要这种初始化,而不仅仅是糖。
对于问题的第二部分:这更多的是风格问题,但如果你有一个关键属性,我就不会创建一个默认值的构造函数。使客户端代码显式设置值。我也不确定为什么要做这样的事情:b = A(true) {foo = false};
除非你参加代码混淆竞赛,否则将是一个好主意。
虽然有点谨慎:
...如果默认构造函数在类中声明为private, 需要公共访问的对象初始值设定项将失败。
答案 1 :(得分:34)
对象初始化器只是语法糖,在编译的程序集IL中它们转换为单独的语句,在ILSpy上检查。
答案 2 :(得分:16)
首先出现构造函数,然后是对象初始值设定项。记住那个
a = new A() { foo = false };
与
相同var temp = new A();
temp.foo = false;
a = temp;
答案 3 :(得分:11)
b = new A(true) {foo = false};
实际上是简称:
A temp = new A(true);
temp.foo = false;
A b = temp;
其中temp
是一个无法访问的变量。始终首先执行构造函数,然后执行任何初始化的属性。
答案 4 :(得分:4)
基本上保罗已经联系到了什么:
来自C# 5 language specification(7.6.10.1)
Processing of an object creation expression that includes an object initializer or
collection initializer consists of first processing the instance constructor and then
processing the member or element initializations specified by the object initializer or
collection initializer.