7

I just noticed that the following is possible in C# written in Visual Studio 2015, but I've never seen it before:

public class X
{
    public int A { get; set; }

    public Y B { get; set; }
}

public class Y
{
    public int C {get; set; }
}

public void Foo()
{
    var x = new X { A = 1, B = { C = 3 } };
}

My expectation was for Foo to have to be implemented like this:

public void Foo()
{
    var x = new X { A = 1, B = new Y { C = 3 } };
}

Note that there is no need to call new Y.

Is this new in C# 6? I haven't seen any mention of this in the release notes, so maybe it's always been there?

jonnystoten
  • 7,055
  • 2
  • 28
  • 36
  • Possible duplicate of [C# object initialization bug?](http://stackoverflow.com/questions/32342188/c-sharp-object-initialization-bug) – Jeroen Vannevel Oct 04 '15 at 19:09

2 Answers2

11

You will get a NullReferenceException if you run this code.

It will not create an instance of Y, it will call the getter of X.B property and try to assign value to property C.

It always worked like that. According to C# 5.0 language specification:

A member initializer that specifies an object initializer after the equals sign is a nested object initializer, i.e. an initialization of an embedded object. Instead of assigning a new value to the field or property, the assignments in the nested object initializer are treated as assignments to members of the field or property.

Jakub Lortz
  • 14,616
  • 3
  • 25
  • 39
  • You are right, thanks. So we can change the declaration of `X.B` to look like `public Y B { get; } = new Y();` and this code will work as expected. Weird that I've never noticed this syntax before! – jonnystoten Oct 01 '15 at 22:31
  • 2
    This feature was introduced in C# 3.0 – Vova Oct 01 '15 at 22:46
6

This feature was introduced in C# 3.0 as object initializers.

See example on p. 169 of C# Language 3.0 specification:

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

which has the same effect as

Rectangle __r = new Rectangle();
__r.P1.X = 0;
__r.P1.Y = 1;
__r.P2.X = 2;
__r.P2.Y = 3;
Rectangle r = __r;
Vova
  • 1,356
  • 1
  • 12
  • 26