使用嵌套对象时对象初始化器中的赋值顺序
Order of assignments in object-initializer when using nested objects
我有以下代码使用对象初始化程序创建 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
我问的原因是 getter 和 setter 修改给定 Root
的 Person
非常复杂,我想避免为了设置 Person
.
的属性而调用它的 getters
我们可以通过在 getter 中为 Root
-class 中的 Person
设置一个断点来轻松检查这一点。调试时我们注意到它从未命中。
这确实导致创建了以下 object-graph:
var p = new Person();
p.Age = 20;
p.Name = "Hans";
var r = new Root();
r.Person = p;
您没有看到 getter 被访问以设置人员属性,因为 Person
是 first 在任何 Root
之前创建的甚至存在。
这确保 Root
仅在先前已完全创建 Person
时才完全创建。
这在 C# 语言规范的 7.6.10.2 中有明确说明。
标准给出了这个例子 "nested object initializer":
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.P1
和 Rectangle.P2
属性是从 already-created Point
对象初始化的。
这证明了你问题的答案
Is Person completely created and than assigned to the new instance of Root?
肯定是:是。
我有以下代码使用对象初始化程序创建 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
我问的原因是 getter 和 setter 修改给定 Root
的 Person
非常复杂,我想避免为了设置 Person
.
我们可以通过在 getter 中为 Root
-class 中的 Person
设置一个断点来轻松检查这一点。调试时我们注意到它从未命中。
这确实导致创建了以下 object-graph:
var p = new Person();
p.Age = 20;
p.Name = "Hans";
var r = new Root();
r.Person = p;
您没有看到 getter 被访问以设置人员属性,因为 Person
是 first 在任何 Root
之前创建的甚至存在。
这确保 Root
仅在先前已完全创建 Person
时才完全创建。
这在 C# 语言规范的 7.6.10.2 中有明确说明。
标准给出了这个例子 "nested object initializer":
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.P1
和 Rectangle.P2
属性是从 already-created Point
对象初始化的。
这证明了你问题的答案
Is Person completely created and than assigned to the new instance of Root?
肯定是:是。