tags:

views:

181

answers:

5

I can initialize a List<int> like new List<int>{1,2,3,4,5}; However List<T> does not have a constructor which accepts a single parameter. So I tried to run this through the debugger and it seems to be calling the Add method. So how does the compiler know which method to invoke to add each individual element.

This may be a silly question but I am a bit confused.

Thanks

+7  A: 

Every type that has the method Add and implements IEnumerable can be initialized this way. The compiler just compiles your code as if you used this Add method.

take a look here

Itay
Not quite - it has to implement IEnumerable as well (and the Add method has to have parameters, and there has to be an accessible constructor).
Jon Skeet
just edited it :) forgot to write it in the first place :)
Itay
+2  A: 

new List{ 1, 2, 3, 4, 5 } is just syntactic 'sugar'. Under the covers it will simply call the Add method for each item.

Mitch Wheat
Would the downvoter please leave a comment. Thanks.
Mitch Wheat
hmmm, no-one owning up to downvoting a correct answer. Democracy at work!
Mitch Wheat
+4  A: 

Look at this method.

    public void CreateList()
    {
        List<int> list = new List<int> { 1, 2, 3, 4, 5 };
    }

After compiling this, the MSIL looks like this..

.method public hidebysig instance void  CreateList() cil managed
{
  // Code size       50 (0x32)
  .maxstack  2
  .locals init ([0] class [mscorlib]System.Collections.Generic.List`1<int32> list,
           [1] class [mscorlib]System.Collections.Generic.List`1<int32> '<>g__initLocal0')
  IL_0000:  nop
  IL_0001:  newobj     instance void class [mscorlib]System.Collections.Generic.List`1<int32>::.ctor()
  IL_0006:  stloc.1
  IL_0007:  ldloc.1
  IL_0008:  ldc.i4.1
  IL_0009:  callvirt   instance void class [mscorlib]System.Collections.Generic.List`1<int32>::Add(!0)
  IL_000e:  nop
  IL_000f:  ldloc.1
  IL_0010:  ldc.i4.2
  IL_0011:  callvirt   instance void class [mscorlib]System.Collections.Generic.List`1<int32>::Add(!0)
  IL_0016:  nop
  IL_0017:  ldloc.1
  IL_0018:  ldc.i4.3
  IL_0019:  callvirt   instance void class [mscorlib]System.Collections.Generic.List`1<int32>::Add(!0)
  IL_001e:  nop
  IL_001f:  ldloc.1
  IL_0020:  ldc.i4.4
  IL_0021:  callvirt   instance void class [mscorlib]System.Collections.Generic.List`1<int32>::Add(!0)
  IL_0026:  nop
  IL_0027:  ldloc.1
  IL_0028:  ldc.i4.5
  IL_0029:  callvirt   instance void class [mscorlib]System.Collections.Generic.List`1<int32>::Add(!0)
  IL_002e:  nop
  IL_002f:  ldloc.1
  IL_0030:  stloc.0
  IL_0031:  ret
} // end of method Program::CreateList

As you can observe, It's just a syntactic sugar and the compiler replaces the intialization by consecutive calls of Add().

this. __curious_geek
+7  A: 

This is a collection initializer, a C# 3.0 language feature. It requires:

  • the type must implement IEnumerable (although this is never used for initialization)
  • the type must have at least one Add method

It simply calls the Add method for each term. You can also use tuples if the Add accepts multiple values, for example dictionaries. Each term is then {key,value}:

new Dictionary<int,string> {{1,"abc"},{2,"def"}};

For an example of using this for a bespoke type:

class Program
{
    static void Main()
    {
        new Foo { 1, "abc", { 2, "def" } };
    }
}

class Foo : IEnumerable
{
    public void Add(int a) { }
    public void Add(string b) { }
    public void Add(int a, string b) { }
    // must implement this!! (but never called)
    IEnumerator IEnumerable.GetEnumerator() { throw new NotImplementedException(); }
}
Marc Gravell
A: 

As new List<int>{1,2,3,4,5} is array initialization, i prefer to think it works this out internally by magic since i can't effect the way it happens. Coming to think of it, it probably defines the default method for adding elements to the collection in metadata where [] is done by index and those that implement IList are done by the Add method.

Bablo
At isn't "array initialization" - that is a separate topic that works very differently. And as it *happens* it doesn't rely on `IList.Add` either (but that is a reasonable supposition).
Marc Gravell
I meant to say collection initialization, also this could be helpful to the OPhttp://stackoverflow.com/questions/459652/why-do-c-collection-initializers-work-this-way
Bablo