使用嵌套对象时,对象初始值设定项中的赋值顺序

时间:2017-01-27 11:44:05

标签: c# object-initializers

我有以下代码使用object-initializer创建Root的实例:

var r = new Root { Person = new Person { Age = 20, Name = "Hans" } };

来自Is there any benefit of using an Object Initializer?我知道如果我们只有内部对象Person,则会将其翻译为以下内容:

var p = new Person();
p.Age = 20;
p.Name = 20;

我想知道这是如何影响我的第一个例子中的嵌套对象的? Person是否已完全创建并分配给Root的新实例,或者仅仅转换为以下内容:

var r = new Root();
r.Person = new Person();
r.Person.Age = 20;          // this would call the Persons getter
r.Person.Name = "Hans";     // this would call the Persons getter

我问的原因是为给定Person修改Root的getter和setter非常复杂,我想避免为了设置属性而调用其getter对于Person

2 个答案:

答案 0 :(得分:2)

这在C#语言规范的7.6.10.2中明确提到。

该标准为“嵌套对象初始化器”提供了此示例:

public class Point
{
    int x, y;
    public int X { get { return x; } set { x = value; } }
    public int Y { get { return y; } set { y = value; } }
}

public class Rectangle
{
    Point p1, p2;
    public Point P1 { get { return p1; } set { p1 = value; } }
    public Point P2 { get { return p2; } set { p2 = value; } }
}

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

标准说这与下面的效果相同:

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

您可以在此处看到Rectangle.P1Rectangle.P2属性是从已创建的Point对象初始化的。

这证明了你问题的答案

  

是否完全创建了Person并将其分配给Root的新实例?

明确地说:是的。

答案 1 :(得分:1)

我们可以通过在Person - 类中的Root的getter中设置断点来轻松检查这一点。调试时我们注意到它从未被击中。

这确实导致创建了以下对象图:

var p = new Person();
p.Age = 20;
p.Name = "Hans";

var r = new Root();
r.Person = p;

您看到没有访问任何getter来设置人员属性,因为Person是先创建 ,而Root甚至存在之前。

这可确保仅在先前已完全创建Root时才完全创建Person