maxp
maxp

Reputation: 25161

What is this syntax using new followed by a list inside braces?

Ive just seen a piece of code that uses a generic list class to instantiate itself in the following manner:

var foo = new List<string>(){"hello", "goodbye"};

The curly braces after the contructor are especially confusing. It reminds me somewhat of

var bar = new string[]{"hi","bye"};

but in the past i've wouldve always used:

var foo = new List<string>(new []{"hello", "goodbye"});

Has anybody got a link explaining the syntax in the first line of code? I wouldnt even know where to begin with googling it.

Upvotes: 22

Views: 9390

Answers (5)

phoog
phoog

Reputation: 43056

This is a collection initializer: http://msdn.microsoft.com/en-us/library/bb384062.aspx

The type so initialized must implement IEnumerable and have an Add method. The items in the curly-brace list are passed to the add method; different items in the list could be passed to different Add methods. If there's an Add overload with more than one argument, you put the multiple arguments in a comma-separated list enclosed in curly braces.

For example:

class MyWeirdCollection : IEnumerable
{
    public void Add(int i) { /*...*/ }
    public void Add(string s) { /*...*/ }
    public void Add(int i, string s) { /*...*/ }

    //IEnumerable implementation omitted for brevity
}

This class could be initialized thus:

var weird = new MyWeirdCollection { 1, "Something", {5, "Something else"} };

This compiles to something like this:

var temp = new MyWeirdCollection();
temp.Add(1);
temp.Add("Something");
temp.Add(5, "Something else");
var weird = temp;

In his blog post (link posted by Eric Lippert in the comments), Mads Torgersen expresses this concisely:

The list you provide is not a “list of elements to add”, but a “list of sets of arguments to Add methods”. ...[W]e do separate overload resolution against Add methods for each entry in the list.

Upvotes: 17

Eric Lippert
Eric Lippert

Reputation: 660397

As others have pointed out, that is a collection initializer. Some other features you might not be aware of that were added to C# 3:

  • A collection initializer constructor may omit the parentheses if the argument list is empty. So new List<int> { 10, 20, 30 } is fine.
  • An array initialized with an array initializer may in some cases omit the type. For example, var myInts = new[] { 10, 20, 30}; infers that myInts is int[].
  • Objects may be initialized using a similar object initializer syntax. var c = new Customer() { Name = "Fred" }; is the same as var temp = new Customer(); temp.Name = "Fred"; var c = temp;

The point of these features is to (1) make more things that used to require statements into things that require only expressions; LINQ likes things to be expressions, and (2) to enable richer type inference, particularly for anonymous types.

Finally: there has been some confusion in some of the answers and comments regarding what is required for a collection initializer. To be used with a collection initializer the type must (1) implement IEnumerable (so that we know it is a collection) and (2) have an Add method (so that we can add stuff to it.)

See

http://blogs.msdn.com/b/madst/archive/2006/10/10/what-is-a-collection_3f00_.aspx

for additional thoughts on the design of the feature.

Upvotes: 37

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726889

This is a collection initializer. You can use it on collections with an Add method.

The pair of parentheses before the curly braces is optional.

This is very convenient, because you can use it on collections other than lists, for example on dictionaries:

var x = new Dictionary<int,string> {{1, "hello"}, {2, "world"}};

This lets you avoid a lengthier initialization sequence:

var x = new Dictionary<int,string>();
x.Add(1, "hello");
x.Add(2, "world");

Upvotes: 2

Servy
Servy

Reputation: 203844

In the third line of code you provided you are making a new string array, and then passing that string array to the list. The list will then add each of those items to the list. This involves the extra overhead of allocating the array, populating it, and then discarding it.

There is a mechanism for a class to define how to use Collection Initializers to populate itself. (See the other answers) I have never found the need to utilize this for my own classes, but existing data structures such as List, Dictionary, often define them, and they are useful to use.

Upvotes: 2

mindandmedia
mindandmedia

Reputation: 6825

here you go. The keyword is "Array Initializers".

http://msdn.microsoft.com/en-us/library/aa664573(v=vs.71).aspx

or rather "Collection Initializers"

http://msdn.microsoft.com/en-us/library/bb384062.aspx

Upvotes: 30

Related Questions