2009-04-15 11 views
46

En C#, je peux initialiser une liste en utilisant la syntaxe suivante.Initialisation d'une liste générique en C#

List<int> intList= new List<int>() { 1, 2, 3 }; 

Je voudrais savoir comment cette syntaxe {} fonctionne, et si elle a un nom. Il y a un constructeur qui prend un IEnumerable, vous pourriez appeler ça.

List<int> intList= new List<int>(new int[]{ 1, 2, 3 }); 

Cela semble plus "standard". Lorsque je déconstruis le constructeur par défaut pour la liste, je ne vois que

this._items = Array.Empty; 

Je voudrais pouvoir le faire. Vous pouvez utiliser la liste 1, 2, 3. Comment cela marche-t-il?

Mise à jour

Jon Skeet a répondu

qu'il appelle le constructeur parameterless, puis appeler Ajouter:

> List<int> tmp = new List<int>(); 
> tmp.Add(1); tmp.Add(2); tmp.Add(3); 
> List<int> intList = tmp; 

Je comprends ce qui est fait. Je veux savoir comment. Comment cette syntaxe sait-elle appeler la méthode Add?

Mise à jour

Je sais, comment accepter cliche une réponse Jon Skeet. Mais, l'exemple avec les cordes et les ints est génial. Aussi une page MSDN très utile est:

Répondre

64

Ceci est appelé un initialiseur de collection . Il est d'appeler le constructeur parameterless, puis appeler Ajouter:

List<int> tmp = new List<int>(); 
tmp.Add(1); 
tmp.Add(2); 
tmp.Add(3); 
List<int> intList = tmp; 

Les exigences du type sont:

  • Il implémente IEnumerable
  • Il a une surcharge de Add qui sont appropriés pour les types d'arguments que vous la fourniture. Vous pouvez fournir plusieurs arguments entre accolades, auquel cas le compilateur recherche une méthode Add avec plusieurs paramètres.

Par exemple:

public class DummyCollection : IEnumerable 
{ 
    IEnumerator IEnumerable.GetEnumerator() 
    { 
     throw new InvalidOperationException("Not a real collection!"); 
    } 

    public void Add(string x) 
    { 
     Console.WriteLine("Called Add(string)"); 
    } 

    public void Add(int x, int y) 
    { 
     Console.WriteLine("Called Add(int, int)"); 
    } 
} 

Vous pouvez ensuite utiliser:

DummyCollection foo = new DummyCollection 
{ 
    "Hi", 
    "There", 
    { 1, 2 } 
}; 

(Bien sûr, normalement vous voudriez votre collection pour mettre en œuvre correctement IEnumerable ...)

+0

Dommage que les arguments aient été inversés - mais corrigés maintenant :) –

+0

Alors, pourquoi est-ce que le type est énumérable? il ne semble pas ajouter autre chose que de rendre C# plus conscient de .NET, similaire à IDisposable .. me fait me demander pourquoi foreach nécessite juste une signature compat, et non des interfaces .. Je pensais que l'idée était si C# ne serait pas spécifiquement lié à un 'lang' – meandmycode

+2

@meandmycode: foreach n'est pas lié à IEnumerable car les pré-génériques il n'y avait pas d'autre moyen d'exposer un itérateur sans boxe. Avec les génériques, je suis sûr que ça aurait * juste * reposé sur IEnumerable . (Suite) –

1

Je crois que c'est un raccourci vers la méthode .Add. Cependant, je n'ai jamais essayé de le contourner, donc je ne sais pas si c'est possible.

+0

Il est possible, essayez d'implémenter un IDictionary –

0

En ce qui me concerne, l'ajout d'éléments via l'initialisation d'objet recherche une méthode Add. Donc, comme la liste < int> aura void Add (int), cela fonctionnera.

Pour l'utiliser dans votre classe, il suffit d'ajouter

class CustomClass { 
    public void Add(int num) { 
     // Your code here 
    } 
} 

Votre classe doit mettre en œuvre IEnumerable, comme Hallgrim souligné.

4

Ils sont appelés collection initializers (voir également here), et leur fonctionnement dépend de la recherche d'une méthode Add() pouvant répondre à leurs appels d'offres. Il appelle Add() pour chacun des entiers que vous avez dans vos accolades.

La recherche de la méthode Add() est pure magie du compilateur. Il est codé en dur pour trouver une méthode de ce nom.

+0

Vous ne savez pas où vous avez le mot "default" à partir de là - ce ne sont que des "initialiseurs de collection". –

+0

Assez juste, je l'ai changé. – mquander

0

Il utilise en fait la méthode .Add. Ce qui signifie qu'il appelle .Add pour chaque élément entre parenthèses à l'intérieur du constructeur.