Kann ich einen Sammlungsinitialisierer für Wörterbucheinträge <TKey, TValue> verwenden?

94

Ich möchte einen Sammlungsinitialisierer für das nächste Codebit verwenden:

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

Normalerweise sollte es so etwas sein wie:

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

Aber wie lautet die richtige Syntax dafür?

Gerrie Schenck
quelle
Überprüfen Sie diesen Beitrag: marcin-chwedczuk.github.io/…
csharpfolk
Ich glaube nicht, dass das ein Betrug ist, weil sie nicht nach der Syntax der Kurzwörterbuchdeklaration gefragt haben, sondern danach, warum die Kurzschrift in ihrem (alten) Setup nicht funktioniert hat.
NH.

Antworten:

156
var names = new Dictionary<int, string> {
  { 1, "Adam" },
  { 2, "Bart" },
  { 3, "Charlie" }
};
bruno conde
quelle
1
Wann funktioniert der Initialisierer? Ist es nur für Dictionary<TKey, TValue>Unterklassen oder wird es auch funktionieren ICollection<KeyValuePair<TKey, TValue>>?
Shimmy Weitzhandler
nach C # 3.0 können Sie varanstelle des deklarierenden Typs verwenden, oder wenn Sie den deklarierenden Typ verlassen, können Sie den new Dictio...- stackoverflow.com/questions/5678216/…
drzaus
1
@drzaus: Die Verwendung von var ist jedoch eine hässliche, hässliche Praxis. C # ist eine stark typisierte Sprache.
Nyerguds
1
@ Nyerguds: was? varspart buchstäblich nur Tastatureingaben, es ist implizit stark typisiert .
Drzaus
4
@Nyerguds - Sie haben ein Recht auf Ihre Meinung, aber wenn Sie Ihre Variablen sofort initialisieren, gibt es buchstäblich keinen Unterschied zwischen der Verwendung varund der Wiederholung mit SomeType obj = new SomeType.... Und da Sie nicht deklarieren können, var obj;ohne sofort zu initialisieren, sehe ich das Problem einfach nicht. Wirklich, ich versuche zu lernen, aber ich kann Ihre Position nicht verbessern.
Drzaus
35

Die Syntax ist etwas anders:

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

Beachten Sie, dass Sie effektiv Tupel von Werten hinzufügen.

Als Randnotiz: Auflistungsinitialisierer enthalten Argumente, die im Grunde genommen Argumente für jede Add () - Funktion sind, die in Bezug auf den Argumenttyp zur Kompilierungszeit nützlich ist. Das heißt, wenn ich eine Sammlung habe:

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

    public void Add(string s) ...

    public void Add(double d) ...
}

Der folgende Code ist völlig legal:

var foos = new FooCollection() { 1, 2, 3.14, "Hello, world!" };
Anton Gogolev
quelle
Tolle Antwort, das wusste ich nicht! Wann funktioniert der Wörterbuchinitialisierer? Ist es nur für Dictionary <TKey, TValue> -Unterklassen oder funktioniert es auch mit ICollection <KeyValuePair <TKey, TValue >>?
Shimmy Weitzhandler
@ Shimmy Collection-Initialisierer arbeiten mit allem, was Methoden implementiert IEnumerable und enthält Add().
Anton Gogolev
@ Shimmy: Wörterbücher sind Sammlungen
John Saunders
@ JohnSaunders Ein Wörterbuchinitialisierer akzeptiert jedoch zwei Parameter für Add.
Shimmy Weitzhandler
2
@ Shimmy: Warum ist das wichtig? Der Punkt ist, dass es mit jeder Klasse funktioniert , die implementiert IEnumerable<T>und eine AddMethode hat. Wenn die AddMethode 3 Parameter akzeptiert, benötigen Sie 3 Objekte in den Klammern.
John Saunders
11
return new Dictionary<int, string>
{ 
   { 1, "Adam" },
   { 2, "Bart" },
   ...
ybo
quelle
10

Die Frage ist markiert c#-3.0, aber der Vollständigkeit halber erwähne ich die neue Syntax, die mit C # 6 verfügbar ist, falls Sie Visual Studio 2015 (oder Mono 4.0) verwenden:

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

Hinweis: Die in anderen Antworten erwähnte alte Syntax funktioniert jedoch immer noch, wenn Ihnen das besser gefällt. Der Vollständigkeit halber hier noch einmal die alte Syntax:

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

Eine andere coole Sache ist, dass Sie mit jeder Syntax das letzte Komma lassen können, wenn Sie möchten, was das Kopieren / Einfügen zusätzlicher Zeilen erleichtert. Zum Beispiel kompiliert das Folgende ganz gut:

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

Wenn Sie nach einer etwas weniger ausführlichen Syntax suchen, können Sie eine Unterklasse von Dictionary<string, object>(oder was auch immer Ihr Typ ist) wie folgt erstellen :

public class DebugKeyValueDict : Dictionary<string, object>
{

}

Dann initialisiere einfach so

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

Welches ist gleichbedeutend mit

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

Der Vorteil besteht darin, dass Sie alle kompilierten Inhalte erhalten, die Sie möglicherweise benötigen, z

is DebugKeyValueDict anstatt is IDictionary<string, object>

oder Ändern der Typen des Schlüssels oder Werts zu einem späteren Zeitpunkt. Wenn Sie so etwas auf einer Rasiermesser-cshtml-Seite tun, ist es viel schöner anzusehen.

Sie sind nicht nur weniger ausführlich, sondern können dieser Klasse auch zusätzliche Methoden hinzufügen, für was auch immer Sie möchten.

Simon_Weaver
quelle
Dies ist im Grunde, wie ein ViewDataDictionary in MVC funktioniert - stackoverflow.com/questions/607985/…
Simon_Weaver
Ich habe mit Typen als 'Aliase' für Wörterbücher und typisierte Arrays experimentiert und angenommen, dass es in einer typisierten Welt sicherer wäre, vordefinierte Typen zu verwenden. Es stellte sich heraus, dass sie in Bezug auf Generika und Linq nicht so nützlich sind.
Patrick
1

Im folgenden Codebeispiel wird a Dictionary<TKey, TValue>mit Instanzen vom Typ initialisiert 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}}
  };

von msdn

Bellash
quelle
-3

Ja, wir können den Sammlungsinitialisierer im Wörterbuch verwenden. Wenn wir ein Wörterbuch wie dieses haben,

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

Wir können es wie folgt initialisieren.

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

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

            }; 
Debendra Dash
quelle
4
Es gibt bereits 6 weitere Antworten, die zeigen, wie das geht. Wir brauchen keine 7. Antwort, die dasselbe zeigt.
Servy