web-dev-qa-db-fra.com

Plusieurs paramètres dans une liste en C #. Comment créer sans classe?

C'est probablement une question assez évidente, mais comment pourrais-je créer une List ayant plusieurs paramètres sans créer de classe.

Exemple:

var list = new List<string, int>();

list.Add("hello", 1);

J'utiliserais normalement une classe comme celle-ci:

public class MyClass
{
    public String myString {get; set;}
    public Int32 myInt32 {get; set;}
}

puis créez ma liste en faisant:

var list = new List<MyClass>();
list.Add(new MyClass { myString = "hello", myInt32 = 1 });
47
Darcy

Si vous utilisez .NET 4.0, vous pouvez utiliser une variable Tuple .

List<Tuple<T1, T2>> list;

Pour les anciennes versions de .NET, vous devez créer une classe personnalisée (sauf si vous avez la chance de pouvoir trouver une classe qui correspond à vos besoins dans la bibliothèque de classes de base).

73
Mark Byers

Si les éléments ne vous dérangent pas, vous pouvez utiliser la classe Tuple ajoutée à .net 4

var list = new List<Tuple<string,int>>();
list.Add(new Tuple<string,int>("hello", 1));

list[0].Item1 //Hello
list[0].Item2 //1

Cependant, si vous ajoutez deux éléments à chaque fois et que l’un d’eux est un identifiant unique, vous pouvez utiliser un Dictionnaire

20
Scott Chamberlain

Si nécessaire, vous pouvez utiliser un dictionnaire qui est également une collection générique:

Dictionary<string, int> d = new Dictionary<string, int>();
d.Add("string", 1);
6
David

List accepte uniquement un paramètre de type . Le plus proche que vous obtiendrez avec List est:

 var list = new List<Tuple<string, int>>();
 list.Add(Tuple.Create("hello", 1));
4
Richard Hein

Pour ajouter à ce que d’autres suggèrent, j’aime la construction suivante afin d’éviter le désagrément d’ajouter des membres aux collections keyvaluepair.

public class KeyValuePairList<Tkey,TValue> : List<KeyValuePair<Tkey,TValue>>{
    public void Add(Tkey key, TValue value){
        base.Add(new KeyValuePair<Tkey, TValue>(key, value));
    }
}

Cela signifie que le constructeur peut être initialisé avec une meilleure syntaxe:

var myList = new KeyValuePairList<int,string>{{1,"one"},{2,"two"},{3,"three"}};

Personnellement, j'aime bien le code ci-dessus sur les exemples plus verbeux. Malheureusement, C # ne supporte pas vraiment les types Tuple de manière native, donc ce petit bidouillage fonctionne à merveille.

Si vous estimez avoir réellement besoin de plus de 2, je suggère de créer des abstractions contre le type Tuple (bien que Tuple soit une classe et non une structure comme KeyValuePair, il s'agit d'une distinction intéressante).

Curieusement, la syntaxe de la liste d'initialisation est disponible sur n'importe quelle variable IEnumerable et vous permet d'utiliser n'importe quelle méthode Add, même celles qui ne sont pas réellement énumérables par votre objet. C'est assez pratique d'autoriser des choses comme ajouter un membre object[] en tant que membre params object[].

3
Michael B

Une autre solution créer une liste générique de type anonyme.

 var list = new[]
 { 
    new { Number = 10, Name = "Smith" },
    new { Number = 10, Name = "John" } 
 }.ToList();

 foreach (var item in list)
 {
    Console.WriteLine(item.Name);
 }

Cela vous donne également un soutien intellisense, je pense que dans certaines situations, il vaut mieux que Tuple et Dictionary.

3
stom

Obtenez le nom du schéma et le nom de la table à partir d'une base de données. 

        public IList<Tuple<string, string>> ListTables()
        {

            DataTable dt = con.GetSchema("Tables");

            var tables = new List<Tuple<string, string>>();

            foreach (DataRow row in dt.Rows)
            {
            string schemaName = (string)row[1];
            string tableName = (string)row[2];
            //AddToList();
            tables.Add(Tuple.Create(schemaName, tableName));
            Console.WriteLine(schemaName +" " + tableName) ;
            }
            return tables;
        }
1
aditshh

Comme l'ont dit Scott Chamberlain (et plusieurs autres), Tuples fonctionne mieux si vous ne craignez pas d'avoir des objets immuables (c'est-à-dire en lecture seule).

Si, comme David l’a suggéré, vous souhaitez référencer int par la valeur de chaîne, par exemple, vous devez utiliser un dictionnaire.

Dictionary<string, int> d = new Dictionary<string, int>();
d.Add("string", 1);
Console.WriteLine(d["string"]);//prints 1

Toutefois, si vous souhaitez stocker vos éléments de manière mutuelle dans une liste et ne souhaitez pas utiliser un système de référence de type dictionnaire, votre meilleur choix (c'est-à-dire la seule solution réelle à l'heure actuelle) consiste à utiliser KeyValuePair, qui std :: pair pour C #:

var kvp=new KeyValuePair<int, string>(2, "a");
//kvp.Key=2 and a.Value="a";
kvp.Key = 3;//both key and
kvp.Value = "b";//value are mutable

Bien sûr, c'est empilable, donc si vous avez besoin d'un plus grand tuple (comme si vous aviez besoin de 4 éléments), empilez-le. Certes, ça devient très vite moche:

     var quad=new KeyValuePair<KeyValuePair<int,string>, KeyValuePair<int,string>>
                (new KeyValuePair<int,string>(3,"a"),
                new KeyValuePair<int,string>(4,"b"));
//quad.Key.Key=3

Donc, évidemment, si vous deviez le faire, vous devriez probablement également définir une fonction auxiliaire.

Mon conseil est que si votre tuple contient plus de 2 éléments, définissez votre propre classe. Vous pouvez utiliser une déclaration typedef-esque en utilisant:

using quad = KeyValuePair<KeyValuePair<int,string>, KeyValuePair<int,string>>;

mais cela ne facilite pas vos instanciations. Vous passeriez probablement beaucoup moins de temps à écrire les paramètres de modèle et plus de temps sur le code non passe-partout si vous utilisez une classe définie par l'utilisateur lorsque vous travaillez avec des n-uplets de plus de 2 éléments

1
rtpg

Pour ceux qui veulent utiliser une classe.

Créez une classe avec tous les paramètres que vous voulez

Créer une liste avec la classe en paramètre 

class MyClass
        {
            public string S1;
            public string S2;
        }

List<MyClass> MyList= new List<MyClass>();

0
Antonio Leite