62

我最近一直在学习 C# 中的对象初始化程序,但现在我想知道它与构造函数冲突时它是如何工作的。

public class A
{
    public bool foo { get; set; }

    public A()
    {
        foo = true;
    }

    public A(bool bar)
    {
        foo = bar;
    }
}

当我尝试这个时会发生什么?

public class B
{
    private A a = new A() { foo = false };

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

构造函数中的默认值是让一个bool开始为真并且可以更改的好方法吗?

public A(bool bar = true)
{
    foo = bar;
}
4

5 回答 5

51

文档中:

编译器通过首先访问默认实例构造函数然后处理成员初始化来处理对象初始化器。

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

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

不过要小心一点:

...如果默认构造函数在类中声明为私有,则需要公共访问的对象初始化程序将失败。

于 2013-06-26T18:04:40.237 回答
41

对象初始化器只是语法糖,在您编译的程序集 IL 中,它们转换为单独的语句,在ILSpy上检查它。

在此处输入图像描述

于 2013-06-26T18:15:22.220 回答
19

构造函数首先出现,然后是对象初始化器。只要记住这一点

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

var temp = new A();
temp.foo = false;
a = temp;
于 2013-06-26T18:04:20.620 回答
11
b = new A(true) {foo = false};

有效地缩写为:

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

wheretemp是一个无法访问的变量。构造函数总是首先执行,然后是任何初始化的属性。

于 2013-06-26T18:04:35.333 回答
5

基本上保罗已经联系了:

来自C# 5 语言规范(7.6.10.1)

包含对象初始化器或集合初始化器的对象创建表达式的处理包括首先处理实例构造器,然后处理由对象初始化器或集合初始化器指定的成员或元素初始化。

于 2013-06-26T18:10:43.663 回答