Czy mogę użyć inicjatora kolekcji dla wpisów Dictionary <TKey, TValue>?

94

Chcę użyć inicjatora kolekcji dla następnego bitu kodu:

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

Więc zazwyczaj powinno to być coś takiego:

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

Ale jaka jest poprawna składnia tego?

Gerrie Schenck
źródło
Sprawdź ten post: marcin-chwedczuk.github.io/…
csharpfolk
nie myślcie, że to oszustwo, ponieważ pytali nie o składnię deklaracji skróconego słownika, ale o to, dlaczego skrót nie działał w ich (starożytnej) konfiguracji.
NH.

Odpowiedzi:

157
var names = new Dictionary<int, string> {
  { 1, "Adam" },
  { 2, "Bart" },
  { 3, "Charlie" }
};
bruno conde
źródło
1
Kiedy działa inicjator? Czy to tylko dla Dictionary<TKey, TValue>podklas, czy też będzie działać ICollection<KeyValuePair<TKey, TValue>>?
Shimmy Weitzhandler
po C # 3.0 można użyć varzamiast typu deklarującego, lub jeśli opuszczenie typu deklarującego można pominąć new Dictio...- stackoverflow.com/questions/5678216/ ...
drzaus
1
@drzaus: Używanie var jest jednak brzydką, brzydką praktyką; C # jest językiem silnie wpisanym.
Nyerguds
1
@Nyerguds: co? vardosłownie oszczędza ci naciśnięć klawiszy, jest domyślnie silnie wpisany .
drzaus
4
@Nyerguds - myślę, że masz prawo do swojej opinii, ale jeśli natychmiast inicjalizujesz swoje zmienne, dosłownie nie ma różnicy między używaniem vara powtarzaniem się SomeType obj = new SomeType.... A ponieważ nie możesz zadeklarować var obj;bez natychmiastowej inicjalizacji, po prostu nie widzę problemu. Naprawdę próbuję się nauczyć, ale nie mogę określić twojej pozycji.
drzaus
36

Składnia jest nieco inna:

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

Zwróć uwagę, że skutecznie dodajesz krotki wartości.

Na marginesie: inicjatory kolekcji zawierają argumenty, które są w zasadzie argumentami dowolnej funkcji Add (), która jest przydatna w odniesieniu do typu argumentu w czasie kompilacji. To znaczy, jeśli mam kolekcję:

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

    public void Add(string s) ...

    public void Add(double d) ...
}

poniższy kod jest całkowicie legalny:

var foos = new FooCollection() { 1, 2, 3.14, "Hello, world!" };
Anton Gogolev
źródło
Świetna odpowiedź, nie wiedziałem o tym! W każdym razie, kiedy działa inicjator słownika? Czy jest to tylko dla podklas Dictionary <TKey, TValue>, czy też będzie działać na ICollection <KeyValuePair <TKey, TValue >>?
Shimmy Weitzhandler
Inicjatory @Shimmy Collection działają na wszystkim, co implementuje IEnumerable i ma Add()metody.
Anton Gogolev
@Shimmy: słowniki to kolekcje
John Saunders
@JohnSaunders Ale inicjator słownika akceptuje dwa parametry dla Add.
Shimmy Weitzhandler
2
@Shimmy: dlaczego to ma znaczenie? Chodzi o to, że będzie działać z każdą klasą, która implementuje IEnumerable<T>i ma Addmetodę. Jeśli Addmetoda przyjmuje 3 parametry, będziesz potrzebować 3 obiektów w nawiasach.
John Saunders,
11
return new Dictionary<int, string>
{ 
   { 1, "Adam" },
   { 2, "Bart" },
   ...
ybo
źródło
10

Pytanie jest otagowane c#-3.0, ale dla pełnego wyjaśnienia wspomnę o nowej składni dostępnej w C # 6 na wypadek, gdybyś korzystał z Visual Studio 2015 (lub Mono 4.0):

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

Uwaga: stara składnia wspomniana w innych odpowiedziach nadal działa, jeśli wolisz to. Ponownie, dla kompletności, oto stara składnia:

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

Inną fajną rzeczą, na którą należy zwrócić uwagę, jest to, że w każdej składni możesz zostawić ostatni przecinek, jeśli chcesz, co ułatwia kopiowanie / wklejanie dodatkowych linii. Na przykład, kompiluje się dobrze:

var dictionary = new Dictionary<int, string>
{
   [1] = "Adam",
   [2] = "Bart",
   [3] = "Charlie",
};
Nate Cook
źródło
5

Jeśli szukasz nieco mniej szczegółowej składni, możesz utworzyć podklasę Dictionary<string, object>(lub jakikolwiek inny typ) w następujący sposób:

public class DebugKeyValueDict : Dictionary<string, object>
{

}

Następnie po prostu zainicjuj w ten sposób

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

Co jest równoważne

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

Korzyścią jest to, że dostajesz wszystkie rzeczy typu kompilacji, których możesz chcieć, takie jak możliwość powiedzenia

is DebugKeyValueDict zamiast is IDictionary<string, object>

lub zmianę typów klucza lub wartości w późniejszym terminie. Jeśli robisz coś takiego na stronie cshtml maszynki do golenia, jest to o wiele przyjemniejsze.

Oprócz bycia mniej szczegółowym możesz oczywiście dodać dodatkowe metody do tej klasy, co tylko zechcesz.

Simon_Weaver
źródło
Tak w zasadzie działa ViewDataDictionary w MVC - stackoverflow.com/questions/607985/ ...
Simon_Weaver
Eksperymentowałem z typami jako „aliasami” dla słowników i tablicami typowanymi, zakładając, że w świecie pisania bezpieczniej byłoby używać predefiniowanych typów. Okazało się, że nie jest to tak przydatne, jeśli chodzi o typy generyczne i linq.
Patrick,
1

W poniższym przykładzie kodu a Dictionary<TKey, TValue>jest inicjowany z wystąpieniami typu 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}}
  };

z msdn

Bellash
źródło
-3

Tak, możemy użyć inicjatora kolekcji w słowniku.Jeśli mamy taki słownik

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

Możemy go zainicjować w następujący sposób.

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

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

            }; 
Debendra Dash
źródło
4
Istnieje już 6 innych odpowiedzi pokazujących, jak to zrobić. Nie potrzebujemy 7. odpowiedzi, która pokazuje to samo.
Servy