2010-05-28 5 views
15

Ich kann eine List<int> like new List<int>{1,2,3,4,5}; initialisieren List<T> hat jedoch keinen Konstruktor, der einen einzelnen Parameter akzeptiert. Also habe ich versucht, dies durch den Debugger zu starten und es scheint, die Add-Methode aufzurufen. Also, wie weiß der Compiler, welche Methode aufgerufen werden soll, um jedes einzelne Element hinzuzufügen.Liste <int> Initialisierung in C# 3.5

Dies kann eine dumme Frage, aber ich bin ein wenig verwirrt.

Dank

Antwort

9

Jeder Typ, der die Methode Add hat und implementiert IEnumerable können auf diese Weise initialisiert werden. Der Compiler kompiliert nur Ihren Code, als ob Sie diese Add-Methode verwendet hätten.

werfen Sie einen Blick here

+2

Nicht ganz - es hat IEnumerable zu implementieren als auch (und die Add-Methode hat die Parameter haben, und es muss ein leicht zugänglicher Konstruktor sein). –

+0

gerade bearbeitet :) vergessen, es an erster Stelle zu schreiben :) –

2

new List{ 1, 2, 3, 4, 5 } nur syntaktischer 'Zucker' ist. Unter den Deckeln wird einfach die Add Methode für jeden Artikel aufgerufen.

+2

Würde der downvoter bitte einen Kommentar hinterlassen. Vielen Dank. –

+0

hmmm, niemand besitzt bis zur richtigen Antwort eine richtige Antwort. Demokratie bei der Arbeit! –

6

Schauen Sie sich diese Methode.

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

Danach kompilieren, die MSIL wie folgt aussehen ..

.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 

Wie Sie beobachten können, Es ist nur ein syntaktischer Zucker und der Compiler ersetzt die Initialisierung von aufeinander folgenden Aufrufen von Add().

8

Dies ist ein Auflistungsinitialisierer, ein C# 3.0 language feature. Es erfordert:

  • der Typ IEnumerable implementieren müssen (obwohl dies nie für die Initialisierung verwendet wird)
  • die Art mindestens ein Add Methode

für jeden Begriff Es ruft einfach die Add Methode haben muss . Sie können auch Tupel verwenden, wenn Add mehrere Werte akzeptiert, z. B. Wörterbücher. Jeder Begriff ist dann {key,value}:

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

Ein Beispiel für die Verwendung dieser für eine maßgeschneiderte Art:

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

Als new List<int>{1,2,3,4,5} Feldinitialisierung ist, ziehe ich zu denken, dass es das intern aus durch Magie funktioniert, da ich kann nicht die Art beeinflussen, wie es passiert. Kommen Sie zu denken, definiert es wahrscheinlich die Standardmethode für die Elemente der Sammlung in den Metadaten hinzugefügt werden, wobei [] durch den Index erfolgt und diejenigen, die IList implementieren, werden durch die Add Methode.

+0

At ist nicht "Array-Initialisierung" - das ist ein separates Thema, das sehr unterschiedlich funktioniert. Und wie es passiert, ist es nicht auf IList angewiesen.Add "entweder (aber das ist eine vernünftige Annahme). –

+0

Ich wollte Sammlungsinitialisierung sagen, auch dies könnte hilfreich sein für die OP http://stackoverflow.com/questions/459652/why-do-c-collection-initialisers-work-this-way – Bablo