39

Resharper has just suggested the following refactoring to me:

// 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() }
    };

I've never seen this kind of object initialization before. In particular I don't see how

InitializedProperty = { UninitializedSubproperty = new MyOtherClass() }

makes any sense - it's not assigning anything to InitializedProperty.

Is this behaviour specified anywhere?

Rawling
  • 49,248
  • 7
  • 89
  • 127

1 Answers1

56

This syntax is called Object Initialization. C# specification clearly gives a lot of examples on this subject:

7.6.10.2 Object initializers

An object initializer consists of a sequence of member initializers, enclosed by { and } tokens and separated by commas. Each member initializer must name an accessible field or property of the object being initialized, followed by an equals sign and an expression or an object initializer or collection initializer. It is an error for an object initializer to include more than one member initializer for the same field or property. It is not possible for the object initializer to refer to the newly created object it is initializing.

Examples are:

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

Compiles down to:

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

Having:

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; }
}

and

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

Also consider reading a great chapter 8.3 Simplified initialization in C# in depth book. Jon Skeet provides another look at advantages of using this kind of syntax for initializing tree-like structures.

Ilya Ivanov
  • 23,148
  • 4
  • 64
  • 90
  • 1
    Ah, thank you for poniting me at the spec - it's not so easy to find as all the examples online, and *none* of the examples I found did anything other than simple, top-level assignments. The spec *does* say that the object initializer can itself contain object initializers, which I guess is the key point. – Rawling May 28 '13 at 15:01
  • @Rawling yes, there is an pseudocode for `object-initializer`, as C# spec gives for all constructs. I didn't wanted to bring that here, because formatting was completely lost. – Ilya Ivanov May 28 '13 at 15:02
  • Which version of the standard are you referring to? As far as I can tell, the relevant section is 7.6.10.2 in version 4.5 and 5.0. – Jørgen Fogh Jun 23 '14 at 11:31
  • WOW, I also didn't know about this and the specification does not contain any example of this. Very cool and useful feature though. I see there is GitHub issue for that https://github.com/dotnet/docs/issues/12979 – Đonny Nov 07 '19 at 10:13
  • I have a related question. What if there was an extra level of nesting and we had to pass in an argument to "new Point(someArg)", where someArg is defined/set up at construction of Rectangle(). Thanks – toughQuestions Jun 24 '20 at 11:43