2010-11-23 19 views
38

Ceci est probablement une question assez évidente, mais comment pourrais-je créer un List qui a plusieurs paramètres sans créer de classe.Plusieurs paramètres dans une liste en C#. Comment créer sans classe?

Exemple:

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

list.Add("hello", 1); 

Je normalement utiliser une classe comme ceci:

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

puis créer ma liste en faisant:

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

Vous devriez probablement donner un peu plus de détails sur votre problème réel, de sorte que vous compreniez clairement pourquoi vous y parvenez de cette façon. –

+0

Pour quoi voulez-vous utiliser la liste? – Crisfole

+0

Je ne veux pas de dictionnaire. J'essayais d'utiliser un exemple simple ... Je vais utiliser deux chaînes que je reviens au format JSON via ASP.NET MVC 'Controller.Json' – Darcy

Répondre

62

Si vous utilisez .NET 4.0 vous pouvez utiliser un Tuple.

List<Tuple<T1, T2>> list; 

Pour les anciennes versions de .NET, vous devez créer une classe personnalisée (sauf si vous êtes assez chanceux pour être en mesure de trouver une classe qui correspond à vos besoins dans la bibliothèque de classes de base).

+0

+1, bien que Tuple ait été introduit dans .NET 4 donc dans .NET 3.5 Il est toujours coincé en train d'écrire une classe. –

+0

@Jim Schubert: A moins qu'il n'écrive un Tuple ... – David

+0

@David: il demande comment le faire 'sans créer de classe' –

20

Si vous ne dérange pas les éléments étant imutable vous pouvez utiliser la classe Tuple ajouté à .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 

Toutefois, si vous ajoutez deux articles chaque fois et l'un d'entre eux est identifiant unique, vous pouvez utiliser a Dictionary

4

La liste n'accepte qu'un seul paramètre de type. Le plus proche que vous obtiendrez avec liste est la suivante:

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

Le cas échéant, vous pouvez utiliser un dictionnaire qui est aussi une collection générique:

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

+1 c'est exactement ce que j'allais suggérer, mais la partie "params" de la question me porte à croire qu'il cherche plus de deux types. Puisque Dictionary (T, K) et List (T) héritent de IEnumerable et ICollection, ils peuvent être utilisés de manière très similaire. –

+0

ou 'Dictionary > myData = new Dictionary >();' ce que je vais utiliser dans mon cas pour obtenir les données triées par clé – vinsa

0

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

Si, comme suggéré par David, vous voulez faire référence à l'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 mutably dans un liste, et ne veulent pas utiliser un système de référencement de style dictionnaire, alors votre meilleur pari (ie seule solution réelle en ce moment) serait d'utiliser KeyValuePair, qui est essentiellement std :: paire 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 el ements) vous venez de l'empiler. Certes cela devient laid très vite:

 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 

Alors, évidemment, si vous deviez faire, vous devez définir probablement aussi une fonction auxiliaire.

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

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

mais cela ne rend pas votre instanciations plus facile.Vous passeriez probablement beaucoup moins de temps à écrire des paramètres de template et plus de temps sur le code non-standard si vous utilisez une classe définie par l'utilisateur lorsque vous travaillez avec des tuples de plus de 2 éléments

3

comme la construction suivante pour éviter l'ennui 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)); 
    } 
} 

Ce que cela signifie est que le constructeur peut être initialisé avec une meilleure syntaxe ::

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

Personnellement, je aime le code ci-dessus au cours des exemples plus verbeux Malheureusement C# ne supporte pas vraiment les types de tuple en natif ce petit hack fonctionne à merveille. Si vous avez vraiment besoin de plus de 2, je suggère de créer des abstractions contre le type de tuple (bien que Tuple soit une classe pas une structure comme KeyValuePair c'est une distinction intéressante). Curieusement, la syntaxe de la liste d'initialisation est disponible sur n'importe quel 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 pour permettre des choses comme l'ajout d'un membre object[] en tant que membre params object[].

-2

Cela fonctionne bien avec moi

List<string> myList = new List<string>(); 
myList.Add(string.Format("{0}|{1}","hello","1") ; 


label:myList[0].split('|')[0] 
val: myList[0].split('|')[1] 
+0

Ce n'est pas une bonne idée puisque la chaîne eux-mêmes pourraient contenir le | signe, ce qui briserait alors les choses. – Ondrej

0

Pour ceux qui veulent utiliser une classe.

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

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

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

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

1

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 aussi intellisense soutien, je pense que dans certaines situations, mieux que son Tuple et Dictionary.

0

Obtient le nom de schéma et le nom de table d'une base de données. Êtes-vous sûr de vouloir une liste et non un dictionnaire?

 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; 
     }