2013-06-26 104 views
38

我一直在学习C#中的对象初始值设定项,但现在我想知道它在与构造函数冲突时是如何工作的。构造函数与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; 
} 
+18

试试你的例子。 –

+3

代码全部只是运行 – Jonesopolis

+0

是的,它仍然对默认初始化程序有效,但是如果你想要多个参数,你可以忘记的参数只是尾部参数。 – arifnpm

回答

35

documentation

编译器处理由第一访问 默认实例构造函数,然后处理所述构件 初始化对象初始化。

这意味着,在简单的情况下(命名对象的初始化),它基本上是简写(或语法糖)调用默认的构造函数,然后调用属性setter(S)。在匿名类型的情况下,这种初始化实际上是必需的,而不是单纯的糖。

对于你的问题的第二部分:它更多的是风格的问题,但如果你有一个关键的属性,我不会创建一个默认值的构造函数。使客户端代码明确设置值。我也不确定为什么要这样做:b = A(true) {foo = false};会是一个好主意,除非您在代码混淆比赛中。

谨慎位,但:

...如果默认构造函数声明为类私有的,需要公共接入 对象初始化将失败。

15

构造函数首先出现,然后是对象初始值设定项。只要记住,

a = new A() { foo = false }; 

是相同

var temp = new A(); 
temp.foo = false; 
a = temp; 
+0

他们不一样。 'a = new A(); a.foo = false;'如果在给它的属性赋值的时候抛出异常,则保持对象一半被初始化。而使用对象成员会给出意想不到的结果(他们将使用基础类型的默认值,例如布尔成员为false)而不是抛出NullReferenceException。 另一方面,使用Object Initializer或Object构造函数将确保如果发生异常,对象将不会被初始化,并且如果我们尝试使用它的成员(因为它从未被初始化),将会给予NullReferenceException。 – WaelAlshabani

+2

@WaelAlshabani是的,有一个临时对象被创建,然后该属性被设置为它,然后它的引用被分配给该变量。是的,如果你的属性可能抛出一个异常,并且你打算捕捉异常并且由于某种原因仍然使用分配给该变量的引用,那么这是一个微妙但重要的区别。但没有一个适用于这个确切的例子。但我会更新以使其更清楚。 – juharr

11
b = new A(true) {foo = false}; 

是有效简称:

A temp = new A(true); 
temp.foo = false; 
A b = temp; 

其中temp是一个难以接近的变量。构造函数总是先执行,后面是任何初始化的属性。

2

本质保罗已经链接:

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. 
24

对象初始只是语法糖,在乌拉圭回合编译的程序集IL它们转换成单独的语句,检查ILSpy

enter image description here

相关问题