142 votes

Comment initialiser une List<T> à une taille donnée (par opposition à la capacité) ?

.NET propose un conteneur de liste générique dont les performances sont presque identiques (voir la question sur les performances des tableaux et des listes). Cependant, ils sont très différents au niveau de l'initialisation.

Les tableaux sont très faciles à initialiser avec une valeur par défaut, et par définition ils ont déjà une certaine taille :

string[] Ar = new string[10];

ce qui permet d'attribuer en toute sécurité des éléments aléatoires, par exemple :

Ar[5]="hello";

avec une liste, les choses sont plus délicates. Je peux voir deux façons de faire la même initialisation, aucune n'est ce qu'on pourrait appeler élégante :

List<string> L = new List<string>(10);
for (int i=0;i<10;i++) L.Add(null);

ou

string[] Ar = new string[10];
List<string> L = new List<string>(Ar);

Quel serait le moyen le plus propre ?

EDIT : Les réponses données jusqu'à présent font référence à la capacité, ce qui est autre chose que de pré-remplir une liste. Par exemple, sur une liste qui vient d'être créée avec une capacité de 10, on ne peut pas faire L[2]="une valeur".

EDIT 2 : Les gens se demandent pourquoi je veux utiliser les listes de cette façon, car ce n'est pas la façon dont elles sont censées être utilisées. Je vois deux raisons :

  1. On pourrait argumenter de manière tout à fait convaincante que les listes sont les tableaux de "nouvelle génération", ajoutant de la flexibilité sans presque aucune pénalité. On devrait donc les utiliser par défaut. Je signale qu'elles ne sont peut-être pas aussi faciles à initialiser.

  2. Ce que j'écris actuellement est une classe de base offrant une fonctionnalité par défaut dans le cadre d'une structure plus large. Dans la fonctionnalité par défaut que je propose, la taille de la liste est connue à l'avance et j'aurais donc pu utiliser un tableau. Cependant, je veux offrir à n'importe quelle classe de base la possibilité de l'étendre dynamiquement et j'opte donc pour une liste.

1 votes

"EDIT : Les réponses données jusqu'à présent font référence à la capacité, ce qui est autre chose que de pré-remplir une liste. Par exemple, sur une liste qui vient d'être créée avec une capacité de 10, on ne peut pas faire L[2]="somevalue"". Compte tenu de cette modification, vous devriez peut-être reformuler le titre de la question...

0 votes

Mais, quelle est l'utilité de pré-remplir une liste avec des valeurs vides, car c'est ce que le topicstarter essaie de faire ?

0 votes

Frederik : Exactement. Quand cela serait-il nécessaire... jamais ?

1voto

Henk Points 574
string [] temp = new string[] {"1","2","3"};
List<string> temp2 = temp.ToList();

0 votes

Que diriez-vous de List<string> temp2 = new List<string>(temp) ; Comme l'OP l'a déjà suggéré.

0 votes

Ed - celui-ci répond en fait à la question - qui ne concerne pas la capacité.

0 votes

Mais le PO a déjà déclaré qu'il n'aimait pas cette solution.

1voto

James Lawruk Points 8106

Vous pouvez utiliser Linq pour initialiser intelligemment votre liste avec une valeur par défaut. (Similaire à La réponse de David B .)

var defaultStrings = (new int[10]).Select(x => "my value").ToList();

Allez plus loin et initialisez chaque chaîne avec des valeurs distinctes "chaîne 1", "chaîne 2", "chaîne 3", etc :

int x = 1;
var numberedStrings = (new int[10]).Select(x => "string " + x++).ToList();

0voto

Josh Points 1714

Si je comprends bien, il n'y a pas de moyen intégré d'initialiser une liste à une taille spécifique sans ajouter manuellement des valeurs vides, est-ce exact ?

J'ai rencontré une situation où cela est nécessaire. Je suis TRÈS novice en matière de sérialisation JSON. S'il existe une meilleure façon de procéder, faites-le moi savoir !

J'utilise CollectionDataContractJsonSerializer pour sérialiser une collection en JSON, mais cette collection doit être un tableau d'éléments int de taille fixe. L'attribut CollectionDataContract doit s'appliquer à une classe, et je ne peux pas hériter d'un tableau. Au lieu de cela, j'hérite de List et je fais une boucle for jusqu'à la taille de la capacité, en ajoutant des valeurs par défaut (0) à la collection dans le constructeur.

Y a-t-il une meilleure façon de procéder ? Merci beaucoup !

0voto

EricBDev Points 339

Un avis sur IList : Remarques sur l'IList de MSDN : " Les implémentations d'IList se répartissent en trois catégories : lecture seule, taille fixe et taille variable. (...). Pour la version générique de cette interface, voir System.Collections.Generic.IList<T> ."

IList<T> n'hérite PAS de IList (mais List<T> met en œuvre à la fois IList<T> y IList ), mais est toujours taille variable . Depuis .NET 4.5, nous avons également IReadOnlyList<T> mais à ma connaissance, il n'existe pas de liste générique à taille fixe qui correspondrait à ce que vous recherchez.

0voto

Abhay Shiro Points 759

Voici un exemple que j'ai utilisé pour mon test unitaire. J'ai créé une liste d'objets de classe. Puis j'ai utilisé forloop pour ajouter le nombre 'X' d'objets que j'attends du service. De cette façon, vous pouvez ajouter/initialiser une liste pour n'importe quelle taille donnée.

public void TestMethod1()
    {
        var expected = new List<DotaViewer.Interface.DotaHero>();
        for (int i = 0; i < 22; i++)//You add empty initialization here
        {
            var temp = new DotaViewer.Interface.DotaHero();
            expected.Add(temp);
        }
        var nw = new DotaHeroCsvService();
        var items = nw.GetHero();

        CollectionAssert.AreEqual(expected,items);

    }

J'espère que j'ai pu vous aider.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X