Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List<int> initialization in C# 3.5

Tags:

c#

.net-3.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

like image 799
josephj1989 Avatar asked May 28 '10 08:05

josephj1989


People also ask

What is initializer list in C?

The initializer list is used to directly initialize data members of a class. An initializer list starts after the constructor name and its parameters.

What is initialization syntax?

C# - Object Initializer Syntax NET 3.5) introduced Object Initializer Syntax, a new way to initialize an object of a class or collection. Object initializers allow you to assign values to the fields or properties at the time of creating an object without invoking a constructor. Example: Object Initializer Syntax.

What are the different types for initializing an array?

There are two ways to specify initializers for arrays: With C89-style initializers, array elements must be initialized in subscript order. Using designated initializers, which allow you to specify the values of the subscript elements to be initialized, array elements can be initialized in any order.

Why initialization list is used in C++?

Initialization lists allow you to choose which constructor is called and what arguments that constructor receives. If you have a reference or a const field, or if one of the classes used does not have a default constructor, you must use an initialization list.


3 Answers

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(); }
}
like image 196
Marc Gravell Avatar answered Oct 24 '22 10:10

Marc Gravell


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

like image 24
Itay Karo Avatar answered Oct 24 '22 11:10

Itay Karo


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

like image 9
this. __curious_geek Avatar answered Oct 24 '22 10:10

this. __curious_geek