Obtendo um KeyValuePair diretamente de um dicionário

Eu tenho System.Collections.Generic.Dictionary dict onde A e B são classs e uma instância A a (onde dict.ContainsKey(a) é true).

É possível obter o KeyValuePair contendo a diretamente do dictionary?
Ou preciso criar um novo KeyValuePair: new KeyValuePair
(a, dict[a]) ?

Você precisa criar um novo KeyValuePair 1 – mas tenha em mente que o KVP é um tipo de valor (uma struct), então não é como se você estivesse introduzindo uma nova ineficiência fazendo isso. Qualquer método que retorne um KVP seria criar uma cópia de qualquer maneira – você está apenas criando a instância diretamente.

Você sempre pode adicionar um método de extensão a IDictionary se você quiser:

 public static KeyValuePair GetEntry (this IDictionary dictionary, TKey key) { return new KeyValuePair(key, dictionary[key]); } 

Como observado nos comentários, é inteiramente possível que a chave que está armazenada no dictionary não seja a mesma fornecida, apenas semanticamente igual – por alguma semântica que poderia ser customizada por um IEqualityComparer (como em um dictionary que não diferencia maiúsculas de minúsculas, por exemplo). exemplo.) Nesse caso, o código acima não retornaria a input real no dictionary, mas uma input com a chave que você forneceu para procurar. Infelizmente não há maneira eficiente de encontrar a chave original – você teria que fazer uma iteração no dictionary 🙁


1 Eu estava ciente de que você poderia fazer uma iteração sobre as inputs do dictionary e encontrar a input apropriada dessa maneira, mas não vejo razão para que você queira fazer isso quando tiver um indexador perfeitamente bom que seja O (1) em vez de O (N).

Como Dictionary implementa IEnumerable> , você pode usar o linq:

 var pair = _dictionary.SingleOrDefault(p => p.Key == myKey); 

Nós não podemos chegar ao "IPHone" desta forma:

 var dict = new Dictionary(StringComparer.OrdinalIgnoreCase) { { "IPHone", "TCP/IP honing tools" } }; Console.WriteLine(dict["iPhone"]); // "TCP/IP honing tools" Console.WriteLine( ??? ); // "IPHone" 

Parece não haver nenhuma solução O (1) com a API atual, mas o loop de todas as inputs funciona:

 var keyValue = dict.First(p => dict.Comparer.Equals(p.Key, "iPhone")); Console.WriteLine(keyValue.Key); // "IPHone" Console.WriteLine(keyValue.Value); // "TCP/IP honing tools" 

Ou como uma extensão para o preguiçoso:

 [Pure] public static KeyValuePair GetEntry(this Dictionary dictionary, TKey key) { var comparer = dictionary.Comparer; return dictionary.FirstOrDefault(p => comparer.Equals(p.Key, key)); } 

Para mim myDict.AsEnumerable faz isso …