C#中的构造函数与对象初始化程序优先级

bbi*_*ill 53 c# constructor object-initializers

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

public class A
{
    public bool foo { get; set; }
    public A()
    {
        foo = true;
    }
    public A(bool bar)
    {
        foo = bar;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

public class B
{
    a = A() {foo = false};
    b = A(true) {foo = false};
}
Run Code Online (Sandbox Code Playgroud)

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

public A(bar=true)
{
    foo = bar;
}
Run Code Online (Sandbox Code Playgroud)

Pau*_*sik 45

文档:

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

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

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

但有点谨慎:

...如果在类中将默认构造函数声明为private,则需要公共访问的对象初始值设定项将失败.


Tam*_*eer 37

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

在此输入图像描述


juh*_*arr 17

首先是构造函数,然后是对象初始值设定项.记住这一点

a = new A() { foo = false };
Run Code Online (Sandbox Code Playgroud)

和...一样

var temp = new A();
temp.foo = false;
a = temp;
Run Code Online (Sandbox Code Playgroud)

  • @WaelAlshabani是的,有一个临时对象被创建,然后在将引用分配给变量之前将属性设置为它.是的,如果您的属性可能抛出异常并且您计划捕获它并仍然使用由于某种原因分配给变量的引用,那么这是一个微妙但重要的区别.但这些都不适用于这个确切的例子.但我会更新以使其更清楚. (2认同)

Lee*_*Lee 11

b = new A(true) {foo = false};
Run Code Online (Sandbox Code Playgroud)

实际上是:

A temp = new A(true);
temp.foo = false;
A b = temp;
Run Code Online (Sandbox Code Playgroud)

其他地方temp是无法访问的变量.始终首先执行构造函数,然后执行任何初始化的属性.


Chr*_*ris 5

基本上保罗已经链接的内容:

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

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