Método para adicionar novo ou atualizar item existente no dicionário

235

Em algum código legado, vi o seguinte método de extensão para facilitar a adição de um novo item de valor-chave ou a atualização do valor, se a chave já existir.

Método-1 (código herdado).

public static void CreateNewOrUpdateExisting<TKey, TValue>(
    this IDictionary<TKey, TValue> map, TKey key, TValue value)
{            
    if (map.ContainsKey(key))
    {
        map[key] = value;
    }
    else
    {
        map.Add(key, value);
    }
}

No entanto, verifiquei que map[key]=value faz exatamente o mesmo trabalho. Ou seja, esse método pode ser substituído pelo método 2 abaixo.

Método-2.

public static void CreateNewOrUpdateExisting<TKey, TValue>(
    this IDictionary<TKey, TValue> map, TKey key, TValue value)
{
    map[key] = value;
}

Agora, minha pergunta é .. Poderia haver algum problema se eu substituir o método 1 pelo método 2? Vai quebrar em qualquer cenário possível?

Além disso, acho que essa costumava ser a diferença entre HashTable e Dictionary. O HashTable permite atualizar um item ou adicionar um novo item usando o indexador, enquanto o Dictionary não faz !! Essa diferença foi eliminada nas versões C #> 3.0?

O objetivo deste método não é lançar exceção se o usuário enviar o mesmo valor-chave novamente, o método deve apenas atualizar a entrada com o novo valor e criar uma nova entrada se o novo par de valores-chave tiver sido enviado ao método .

Manish Basantani
fonte

Respostas:

243

Poderia haver algum problema se eu substituir o método 1 pelo método 2?

Não, apenas use map[key] = value. As duas opções são equivalentes.


Em relação a Dictionary<>vs Hashtable.: Ao iniciar o Reflector, você vê que os setters do indexador de ambas as classes chamam this.Insert(key, value, add: false);e o addparâmetro é responsável por lançar uma exceção ao inserir uma chave duplicada. Portanto, o comportamento é o mesmo para as duas classes.

ulrichb
fonte
44

Nao há problema. Eu até removeria o CreateNewOrUpdateExistingcódigo-fonte e o usaria map[key] = valuediretamente em seu código, porque isso é muito mais legível, porque os desenvolvedores geralmente sabem o que map[key] = valuesignifica.

Steven
fonte
22

Pergunta antiga, mas acho que devo adicionar o seguinte, ainda mais porque o .net 4.0 já havia sido lançado no momento em que a pergunta foi escrita.

Começando com .net 4.0, existe o espaço para nome System.Collections.Concurrentque inclui coleções que são seguras para threads.

A coleção System.Collections.Concurrent.ConcurrentDictionary<>faz exatamente o que você deseja. Ele possui o AddOrUpdate()método com a vantagem adicional de ser seguro para threads.

Se você estiver em um cenário de alto desempenho e não estiver lidando com vários threads, as respostas já fornecidas map[key] = valueserão mais rápidas.

Na maioria dos cenários, esse benefício de desempenho é insignificante. Nesse caso, aconselho usar o ConcurrentDictionary porque:

  1. Está na estrutura - é mais testado e você não é quem precisa manter o código
  2. É escalável: se você alternar para multithreading, seu código já está preparado para ele
Luis Filipe
fonte
7

Funcionalmente, eles são equivalentes.

Em termos de desempenho, map[key] = valueseria mais rápido, pois você está fazendo apenas uma pesquisa em vez de duas.

Em termos de estilo, quanto menor, melhor :)

Na maioria dos casos, o código parece funcionar bem no contexto de vários segmentos. No entanto, não é seguro para threads sem sincronização extra.

ya23
fonte