MakePeaceGreatAgain
MakePeaceGreatAgain

Reputation: 37095

Order of assignments in object-initializer when using nested objects

I have the following code creating an instance of Root using an object-initializer:

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

From Is there any benefit of using an Object Initializer? I know if we´d have only the inner object Person this was translated to something like this:

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

What I wonder is how does this affect the nested objects in my first example? Is Person completely created and than assigned to the new instance of Root or is this merely translated to something like this:

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

The reason I ask is that the getter and setter to modify a Person for a given Root is quite complex and I´d like to avoid to call its getters for the sake of setting the properties for that Person.

Upvotes: 2

Views: 60

Answers (2)

Matthew Watson
Matthew Watson

Reputation: 109792

This is explicitly addressed in 7.6.10.2 of the C# Language Specification.

The standard gives this example for a "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 }
};

The standard says that this has the same effect as:

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;

Here you can see that the Rectangle.P1 and Rectangle.P2 properties are initialised from already-created Point objects.

This proves that the answer to your question

Is Person completely created and than assigned to the new instance of Root?

is definitively: Yes.

Upvotes: 2

MakePeaceGreatAgain
MakePeaceGreatAgain

Reputation: 37095

We can easily check this out by setting a breakpoint within the getter for Person within the Root-class. When debugging we notice it´s never hit.

This indeed leads to the following object-graph being created:

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

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

You see no getter is accessed in order to set the persons properties because the Person is created first, before any Root even exists.

This ensures that the Root is completely created only if previously a Person has been completely created.

Upvotes: 1

Related Questions