Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Syntactic sugar for adding items to collections in object initialisers

Tags:

syntax

c#

Recently, I came across some code that looked like this:

public class Test
{
    public ICollection<string> Things { get; set; }

    public Test()
    {
        Things = new List<string> { "First" };
    }

    public static Test Factory()
    {
        return new Test
        {
            Things = { "Second" }
        };
    }
}

Calling Test.Factory() results in a Test object with a Things collection containing both "First" and "Second".

It looks like the line Things = { "Second" } calls the Add method of Things. If the ICollection is changed to an IEnumerable, there is a syntax error stating "IEnumerable<string> does not contain a definition for 'Add'".

It is also apparent that you can only use this kind of syntax in an object initialiser. Code such as this is invalid:

var test = new Test();
test.Things = { "Test" };

What is the name of this feature? In which version of C# was it introduced? Why is it only available in object initialisers?

like image 491
Synoptic Avatar asked Feb 01 '17 15:02

Synoptic


1 Answers

It is called a collection initializer and it was added in the C# 3 language specifications (section 7.5.10.3 at introduction, section 7.6.10.3 in the current specs). To be specific, the code you use uses an embedded collection initializer.

Collection initializer actually just call the Add method, which is required according to the specs.

As Quantic commented, the specs say:

A member initializer that specifies a collection initializer after the equals sign is an initialization of an embedded collection. Instead of assigning a new collection to the field or property, the elements given in the initializer are added to the collection referenced by the field or property.

That explains your unexpected results quite good.

Why is it only available in object initialisers?

Because it doesn't make sense elsewhere. You could just call the Add method yourself instead of using initializers for something else than initializing.

like image 90
Patrick Hofman Avatar answered Oct 08 '22 19:10

Patrick Hofman