Posso usar um inicializador de coleção para entradas de Dictionary <TKey, TValue>?


94

Quero usar um inicializador de coleção para o próximo trecho de código:

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

Normalmente, deve ser algo como:

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

Mas qual é a sintaxe correta para isso?


Verifique esta postagem: marcin-chwedczuk.github.io/…
csharpfolk


não pense que isso é um tolo, porque eles estavam perguntando, não pela sintaxe de declaração do dicionário abreviado, mas por que a abreviação não estava funcionando em sua configuração (antiga).
NH.

Respostas:


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

1
Quando o inicializador funciona? É apenas para Dictionary<TKey, TValue>subclasses ou também funcionará ICollection<KeyValuePair<TKey, TValue>>?
Shimmy Weitzhandler

após o C # 3.0, você pode usar em varvez do tipo new Dictio...
declarativo

1
@drzaus: No entanto, usar var é uma prática feia; C # é uma linguagem fortemente tipada.
Nyerguds

1
@Nyerguds: o quê? varliteralmente apenas economiza pressionamentos de teclas, é implicitamente fortemente digitado .
drzaus

4
@Nyerguds - você tem direito à sua opinião, eu acho, mas se você está inicializando imediatamente suas variáveis, não há literalmente nenhuma diferença entre usar vare se repetir com SomeType obj = new SomeType.... E como você não pode declarar var obj;sem inicializar imediatamente, não vejo o problema. Realmente, estou tentando aprender, mas não consigo grocar sua posição.
drzaus 01 de

36

A sintaxe é um pouco diferente:

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

Observe que você está efetivamente adicionando tuplas de valores.

Como nota lateral: os inicializadores de coleção contêm argumentos que são basicamente argumentos para qualquer função Add () que seja útil em relação ao tipo de argumento em tempo de compilação. Ou seja, se eu tiver uma coleção:

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

    public void Add(string s) ...

    public void Add(double d) ...
}

o código a seguir é perfeitamente legal:

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

Ótima resposta, eu não sabia disso! De qualquer forma, quando o inicializador de dicionário funciona? É apenas para subclasses de Dictionary <TKey, TValue> ou também funcionará em ICollection <KeyValuePair <TKey, TValue >>?
Shimmy Weitzhandler

Os inicializadores da coleção @Shimmy funcionam em qualquer coisa que implemente IEnumerable e tenha Add()métodos.
Anton Gogolev

@Shimmy: dicionários são coleções
John Saunders

@JohnSaunders Mas um inicializador de dicionário aceita dois parâmetros para Add.
Shimmy Weitzhandler

2
@Shimmy: por que isso importa? A questão é que funcionará com qualquer classe que implemente IEnumerable<T>e que tenha um Addmétodo. Se o Addmétodo tiver 3 parâmetros, você precisará de 3 objetos entre colchetes.
John Saunders

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

10

A pergunta está marcada c#-3.0, mas para completar, mencionarei a nova sintaxe disponível com C # 6 caso você esteja usando o Visual Studio 2015 (ou Mono 4.0):

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

Nota: a sintaxe antiga mencionada em outras respostas ainda funciona, se você preferir. Novamente, para ser completo, aqui está a sintaxe antiga:

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

Outro tipo de coisa interessante a se notar é que com qualquer sintaxe você pode deixar a última vírgula se desejar, o que torna mais fácil copiar / colar linhas adicionais. Por exemplo, o seguinte compila perfeitamente:

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

5

Se você está procurando uma sintaxe um pouco menos detalhada, pode criar uma subclasse de Dictionary<string, object>(ou qualquer que seja o seu tipo) como esta:

public class DebugKeyValueDict : Dictionary<string, object>
{

}

Então é só inicializar assim

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

Que é equivalente a

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

A vantagem é que você obtém todas as coisas do tipo de compilação que você pode querer, como ser capaz de dizer

is DebugKeyValueDict ao invés de is IDictionary<string, object>

ou alterando os tipos de chave ou valor em uma data posterior. Se você estiver fazendo algo assim em uma página cshtml do razor, é muito mais agradável de olhar.

Além de ser menos prolixo, você pode adicionar métodos extras a esta classe para o que quiser.


É basicamente assim que um ViewDataDictionary funciona no MVC - stackoverflow.com/questions/607985/…
Simon_Weaver

Experimentei tipos como 'aliases' para dicionários e matrizes digitadas, presumindo que seria mais seguro, em um mundo digitado, usar tipos predefinidos. Acabou não sendo tão útil quando se tratava de genéricos e linq.
Patrick

1

No exemplo de código a seguir, a Dictionary<TKey, TValue>é inicializado com instâncias do tipo 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}}
  };

do msdn


-3

Sim, podemos usar o inicializador de coleção no dicionário. Se tivermos um dicionário como este-

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

Podemos inicializá-lo como segue.

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

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

            }; 

4
Já existem 6 outras respostas mostrando como fazer isso. Não precisamos de uma 7ª resposta mostrando a mesma coisa.
Servy
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.