嵌套对象初始化语法

39

Resharper刚刚向我建议了以下重构:

// Constructor initializes InitializedProperty but
// the UninitializedSubproperty is uninitialized.
var myInstance = new MyClass();
myInstance.InitializedProperty.UninitializedSubproperty = new MyOtherClass();

// becomes

var myInstance = new MyClass
    {
        InitializedProperty = { UninitializedSubproperty = new MyOtherClass() }
    };

我以前从未见过这种对象初始化方式。特别是,我不知道如何

InitializedProperty = { UninitializedSubproperty = new MyOtherClass() }

有没有任何意义- 它没有将任何内容“分配”给InitializedProperty

这种行为是否在任何地方有规定?


1
可能是初始化语法的重复问题。 - Stephane Delcroix
1个回答

56

这种语法称为对象初始化。C#规范在这个主题上清楚地给出了很多例子:

7.6.10.2 对象初始化器

对象初始化器包括一系列成员初始化器,由 { 和 } 标记括起来,并用逗号分隔。每个成员初始化器必须命名正在初始化的对象的可访问字段或属性,后跟等号和表达式或对象初始化器或集合初始化器。一个对象初始化器中包含超过一个同一字段或属性的成员初始化器是错误的。无法让对象初始化器引用正在初始化的新创建对象。

例如:

Rectangle r = new Rectangle
            {
                P1 = { X = 0, Y = 1 },
                P2 = { X = 2, Y = 3 }
            };

编译成:

Rectangle r = new Rectangle();
r.P1.X = 0;
r.P1.Y = 1;
r.P2.X = 2;
r.P2.Y = 3;

有:

public class Rectangle
{
    public Rectangle()
    {
        P1 = new Point(); //default Point for demo purpose
        P2 = new Point(); //default Point for demo purpose
    }

    public Point P1 { get; set; }
    public Point P2 { get; set; }
}

public class Point
{
    public int X { get; set; }
    public int Y { get; set; }
}

另外考虑阅读C# in depth一书中伟大的第8.3章 简化初始化。Jon Skeet提供了另一种使用这种语法初始化树状结构的优势的看法。


1
啊,感谢您指出规范 - 它并不像所有在线示例那样容易找到,而且我找到的所有示例都只执行简单的顶层赋值操作。规范确实说对象初始化器本身可以包含对象初始化器,这可能是关键点。 - Rawling
@Rawling 是的,对于“对象初始化器”,有一份伪代码,就像C#规范给出的所有结构一样。我不想在这里提供它,因为格式完全丢失了。 - Ilya Ivanov
你指的是哪个标准的版本?据我所知,相关章节在4.5和5.0版本中的7.6.10.2节。 - Jørgen Fogh
哇,我也不知道这个,而且规范中也没有任何关于它的示例。虽然很酷,但是这个功能非常有用。我看到了 GitHub 的问题 https://github.com/dotnet/docs/issues/12979 - Đonny
我有一个相关的问题。如果有一个额外的嵌套级别,并且我们必须传递一个参数到 "new Point(someArg)",其中 someArg 在 Rectangle() 的构造中定义/设置,那该怎么办?谢谢。 - toughQuestions

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接