Puis-je utiliser un initialiseur de collection pour les entrées Dictionary <TKey, TValue>?


94

Je souhaite utiliser un initialiseur de collection pour le prochain bit de code:

public Dictionary<int, string> GetNames()
{
    Dictionary<int, string> names = new Dictionary<int, string>();
    names.Add(1, "Adam");
    names.Add(2, "Bart");
    names.Add(3, "Charlie");
    return names;
}

Donc, généralement, cela devrait être quelque chose comme:

return new Dictionary<int, string>
{ 
   1, "Adam",
   2, "Bart"
   ...

Mais quelle est la syntaxe correcte pour cela?


Vérifiez cet article: marcin-chwedczuk.github.io
...


ne pensez pas que ce soit une dupe, parce qu'ils demandaient, non pas la syntaxe de déclaration du dictionnaire abrégé, mais pourquoi le raccourci ne fonctionnait pas dans leur (ancienne) configuration.
NH.

Réponses:


157
var names = new Dictionary<int, string> {
  { 1, "Adam" },
  { 2, "Bart" },
  { 3, "Charlie" }
};

1
Quand l'initialiseur fonctionne-t-il? Est-ce uniquement pour les Dictionary<TKey, TValue>sous-classes ou fonctionnera également ICollection<KeyValuePair<TKey, TValue>>?
Shimmy Weitzhandler

après C # 3.0, vous pouvez utiliser à la varplace du type de déclaration, ou si vous quittez le type de déclaration, vous pouvez omettre le new Dictio...- stackoverflow.com/questions/5678216/…
drzaus

1
@drzaus: L'utilisation de var est cependant une pratique laide et laide; C # est un langage fortement typé.
Nyerguds

1
@Nyerguds: quoi? varvous évite littéralement les frappes au clavier, il est implicitement fortement typé .
drzaus

4
@Nyerguds - vous avez droit à votre opinion, je suppose, mais si vous initialisez immédiatement vos variables, il n'y a littéralement aucune différence entre utiliser varet se répéter avec SomeType obj = new SomeType.... Et comme vous ne pouvez pas déclarer var obj;sans initialiser immédiatement, je ne vois tout simplement pas le problème. Vraiment, j'essaie d'apprendre, mais je ne peux pas changer votre position.
drzaus

36

La syntaxe est légèrement différente:

Dictionary<int, string> names = new Dictionary<int, string>()
{
    { 1, "Adam" },
    { 2, "Bart" }
}

Notez que vous ajoutez effectivement des tuples de valeurs.

En remarque: les initialiseurs de collection contiennent des arguments qui sont essentiellement des arguments de la fonction Add () utile en ce qui concerne le type d'argument au moment de la compilation. Autrement dit, si j'ai une collection:

class FooCollection : IEnumerable
{
    public void Add(int i) ...

    public void Add(string s) ...

    public void Add(double d) ...
}

le code suivant est parfaitement légal:

var foos = new FooCollection() { 1, 2, 3.14, "Hello, world!" };

Excellente réponse, je ne savais pas à ce sujet! Quoi qu'il en soit, quand l'initialiseur de dictionnaire fonctionne-t-il? Est-ce uniquement pour les sous-classes Dictionary <TKey, TValue> ou fonctionnera également sur ICollection <KeyValuePair <TKey, TValue >>?
Shimmy Weitzhandler

Les initialiseurs de @Shimmy Collection fonctionnent sur tout ce qui implémente IEnumerable et a des Add()méthodes.
Anton Gogolev

@Shimmy: les dictionnaires sont des collections
John Saunders

@JohnSaunders Mais un initialiseur de dictionnaire accepte deux paramètres pour Add.
Shimmy Weitzhandler

2
@Shimmy: pourquoi est-ce important? Le fait est que cela fonctionnera avec n'importe quelle classe qui implémente IEnumerable<T>et qui a une Addméthode. Si la Addméthode prend 3 paramètres, vous aurez besoin de 3 objets entre parenthèses.
John Saunders du

11
return new Dictionary<int, string>
{ 
   { 1, "Adam" },
   { 2, "Bart" },
   ...

10

La question est balisée c#-3.0, mais par souci d'exhaustivité, je mentionnerai la nouvelle syntaxe disponible avec C # 6 au cas où vous utiliseriez Visual Studio 2015 (ou Mono 4.0):

var dictionary = new Dictionary<int, string>
{
   [1] = "Adam",
   [2] = "Bart",
   [3] = "Charlie"
};

Remarque: l'ancienne syntaxe mentionnée dans d'autres réponses fonctionne toujours si vous aimez mieux cela. Encore une fois, pour être complet, voici l'ancienne syntaxe:

var dictionary = new Dictionary<int, string>
{
   { 1, "Adam" },
   { 2, "Bart" },
   { 3, "Charlie" }
};

Une autre chose intéressante à noter est qu'avec l'une ou l'autre syntaxe, vous pouvez laisser la dernière virgule si vous le souhaitez, ce qui facilite le copier / coller de lignes supplémentaires. Par exemple, ce qui suit se compile très bien:

var dictionary = new Dictionary<int, string>
{
   [1] = "Adam",
   [2] = "Bart",
   [3] = "Charlie",
};

5

Si vous recherchez une syntaxe légèrement moins verbeuse, vous pouvez créer une sous-classe de Dictionary<string, object>(ou quel que soit votre type) comme ceci:

public class DebugKeyValueDict : Dictionary<string, object>
{

}

Ensuite, initialisez simplement comme ça

var debugValues = new DebugKeyValueDict
                  {
                       { "Billing Address", billingAddress }, 
                       { "CC Last 4", card.GetLast4Digits() },
                       { "Response.Success", updateResponse.Success }
                  });

Ce qui équivaut à

var debugValues = new Dictionary<string, object>
                  {
                       { "Billing Address", billingAddress }, 
                       { "CC Last 4", card.GetLast4Digits() },
                       { "Response.Success", updateResponse.Success }
                  });

L'avantage étant que vous obtenez tous les éléments de type de compilation que vous pourriez souhaiter, comme pouvoir dire

is DebugKeyValueDict au lieu de is IDictionary<string, object>

ou en modifiant les types de la clé ou de la valeur à une date ultérieure. Si vous faites quelque chose comme ça dans une page cshtml de rasoir, c'est beaucoup plus agréable à regarder.

En plus d'être moins verbeux, vous pouvez bien sûr ajouter des méthodes supplémentaires à cette classe pour tout ce que vous voudrez.


C'est essentiellement ainsi que fonctionne un ViewDataDictionary dans MVC - stackoverflow.com/questions/607985
...

J'ai expérimenté des types comme «alias» pour les dictionnaires et les tableaux typés, en supposant qu'il serait plus sûr, dans un monde typé, d'utiliser des types prédéfinis. Il s'est avéré que ce n'était pas si utile quand il s'agissait de génériques et de linq.
Patrick

1

Dans l'exemple de code suivant, a Dictionary<TKey, TValue>est initialisé avec des instances de type StudentName.

  Dictionary<int, StudentName> students = new Dictionary<int, StudentName>()
  {
      { 111, new StudentName {FirstName="Sachin", LastName="Karnik", ID=211}},
      { 112, new StudentName {FirstName="Dina", LastName="Salimzianova", ID=317}},
      { 113, new StudentName {FirstName="Andy", LastName="Ruth", ID=198}}
  };

depuis msdn


-3

Oui, nous pouvons utiliser l'initialiseur de collection dans le dictionnaire.Si nous avons un dictionnaire comme celui-ci -

Dictionary<int,string> dict = new Dictionary<int,string>();  
            dict.Add(1,"Mohan");  
            dict.Add(2, "Kishor");  
            dict.Add(3, "Pankaj");  
            dict.Add(4, "Jeetu");

Nous pouvons l'initialiser comme suit.

Dictionary<int,string> dict = new Dictionary<int,string>  
            {  

                {1,"Mohan" },  
                {2,"Kishor" },  
                {3,"Pankaj" },  
                {4,"Jeetu" }  

            }; 

4
Il y a déjà 6 autres réponses montrant comment faire cela. Nous n'avons pas besoin d'une 7ème réponse montrant la même chose.
Servy
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.