开发者

List<int> initialization in C# 3.5

开发者 https://www.devze.com 2023-01-01 14:08 出处:网络
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 si开发者_运维问答ngle parameter.

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 si开发者_运维问答ngle 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


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


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


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().


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


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号