Pourquoi ne puis-je initialiser une Liste comme un tableau en C#?
Aujourd'hui, j'ai été surpris de trouver qu'en C# je peux le faire:
List<int> a = new List<int> { 1, 2, 3 };
Pourquoi ne puis-je faire cela? Ce constructeur est appelé? Comment puis-je faire avec mes propres classes? Je sais que c'est la façon d'initialiser les tableaux, mais les tableaux sont en langue et les Listes sont des objets simples ...
- Cette question peut être vous aider: stackoverflow.com/questions/1744967/...
- Assez impressionnant hein? Vous pouvez le faire très semblable code pour initialiser les dictionnaires ainsi:
{ { "key1", "value1"}, { "key2", "value2"} }
- À partir d'un autre point de vue ce tableau comme syntaxe d'initialisation nous donne un rappel que le type de données d'un
List<int>
est en fait une matrice seule. Je déteste l'équipe C# pour le fait qu'ils ont pas de nom, ilArrayList<T>
qui semble si évident et naturel.
InformationsquelleAutor Ignacio Soler Garcia | 2012-01-13
Vous devez vous connecter pour publier un commentaire.
Cela fait partie de la collection d'initialiseur de la syntaxe .NET. Vous pouvez utiliser cette syntaxe sur toute collection, vous créez tant que:
Il met en œuvre
IEnumerable
(de préférenceIEnumerable<T>
)Il a une méthode nommée
Add(...)
Ce qui se passe est le constructeur par défaut est appelé, et puis
Add(...)
est appelée pour chaque membre de l'initialiseur.Ainsi, ces deux blocs sont à peu près identiques:
Et
Vous peut appeler un autre constructeur, si vous voulez, par exemple pour éviter le sur-dimensionnement de la
List<T>
pendant la culture, etc:Noter que le
Add()
méthode n'a pas besoin de prendre un seul élément, par exemple leAdd()
méthode pourDictionary<TKey, TValue>
prend deux éléments:Est à peu près identique:
Donc, pour l'ajouter à votre propre classe, tout ce que vous devez faire, comme mentionné, est de mettre en œuvre
IEnumerable
(encore une fois, de préférenceIEnumerable<T>
) et de créer un ou plusieursAdd()
méthodes:Alors vous pouvez l'utiliser comme la BCL collections:
(Pour plus d'informations, voir la MSDN)
List<int> temp = new List<int>(); temp.Add(1); ... List<int> a = temp;
Qui est, lea
variable n'est pas initialisée jusqu'à ce que après tous les adds sont appelés. Sinon, il serait légal de faire quelque chose commeList<int> a = new List<int>() { a.Count, a.Count, a.Count };
qui est un truc de fou.List<int> a; a = new List<int>() {a.Count, a.Count, a.Count};
Mais ce n'est certainement juridique et il n'y a rien de mal à cela, car une.Comte de résoudre avant de la main.List<int> a; a = new List<int>() { a.Count };
etList<int> a = new List<int>() { a.Count };
T x = y;
est le même queT x; x = y;
, Ce fait peut conduire à de drôles de situations. Par exemple,int x = M(out x) + x;
est tout à fait légal carint x; x = M(out x) + x;
est légal.IEnumerable<T>
; la non-génériqueIEnumerable
est suffisant pour permettre l'utilisation de la syntaxe d'initialiseur de collection.var x = M(out x) + x;
parce que nous ne pouvons pas déterminer le type de x jusqu'à ce que nous connaissons le type de l'initialiseur, mais nous ne pouvons pas déterminer le type de l'initialiseur, jusqu'à la résolution de surcharge réussit sur M, et de la résolution de surcharge ne peut pas réussir jusqu'à ce que nous connaissons le type de x. Plutôt que d'essayer de résoudre cette "poule et de l'œuf" problème, nous avons tout simplement abandonner.IEnumerable<T>
surIEnumerable
, corrigé.using (var x = new Something{ 1, 2 })
de ne pas disposer de l'objet si l'un desAdd
appels échoue.Il est donc appelé sucre syntaxique.
List<T>
est la "simplicité" de la classe, mais le compilateur donne un traitement spécial afin de rendre votre vie plus facile.Celui-ci est appelé initialiseur de collection. Vous avez besoin de mettre en œuvre
IEnumerable<T>
etAdd
méthode.Selon la Version De C# 3.0 Spécification "L'objet de collection à laquelle un initialiseur de collection est appliqué doit être d'un type qui implémente le Système.Les Collections.Génériques.ICollection exactement un T."
Toutefois, cette information semble être inexactes de cette écriture; voir Eric Lippert de précisions dans les commentaires ci-dessous.
Il fonctionne grâce à initialiseurs de la collection qui, fondamentalement, exigent la collecte de mettre en œuvre une méthode Add et qui va faire le travail pour vous.
Une autre chose cool à propos de la collecte des initialiseurs est que vous pouvez avoir plusieurs surcharges de
Add
méthode et vous pouvez les appeler tous dans le même initialiseur! Par exemple cela fonctionne:Il appelle la bonne surcharges. Aussi, il semble juste pour la méthode avec le nom
Add
, le type de retour pourrait être n'importe quoi.Le tableau comme la syntaxe est transformé en une série de
Add()
appels.Pour voir ce beaucoup plus intéressante exemple, considérons le code suivant dans lequel je fais deux choses intéressantes que son premier illégale en C#, 1) définition d'une propriété readonly, 2) la fixation d'une liste avec un tableau comme initialiseur.
Ce code fonctionne parfaitement, bien que 1) Maliste est en lecture seule et de 2) j'ai mis une liste avec initialiseur de tableau.
La raison pour laquelle cela fonctionne, c'est parce que dans le code qui est une partie d'un objet intializer le compilateur tourne toujours tout
{}
comme la syntaxe d'une série deAdd()
appels qui sont parfaitement légales, même sur un champ en lecture seule.