values initialize c# generics dictionary

initialize - return dictionary c#



Acceso insensible a mayúsculas/minúsculas para diccionario genérico (3)

Tengo una aplicación que usa dlls administrados. Uno de esos dlls devuelve un diccionario genérico:

Dictionary<string, int> MyDictionary;

El diccionario contiene claves con mayúsculas y minúsculas.

Por otro lado, estoy obteniendo una lista de claves potenciales (cadena), sin embargo, no puedo garantizar el caso. Estoy tratando de obtener el valor en el diccionario usando las teclas. Pero, por supuesto, la siguiente falla, ya que tengo una discrepancia en el caso:

bool Success = MyDictionary.TryGetValue( MyIndex, out TheValue );

Esperaba que TryGetValue tuviera un indicador de caso de ignorar como se menciona en el documento de MSDN , pero parece que esto no es válido para diccionarios genéricos.

¿Hay alguna manera de obtener el valor de ese diccionario ignorando el caso clave? ¿Existe una mejor solución que crear una nueva copia del diccionario con el parámetro StringComparer.OrdinalIgnoreCase adecuado?


No es muy elegante, pero en caso de que no puedas cambiar la creación del diccionario, y todo lo que necesitas es un truco sucio, ¿qué tal esto?

var item = MyDictionary.Where(x => x.Key.ToLower() == MyIndex.ToLower()).FirstOrDefault(); if (item != null) { TheValue = item.Value; }


No hay forma de especificar un StringComparer en el punto donde intentas obtener un valor. Si lo piensas bien, "foo".GetHashCode() y "FOO".GetHashCode() son totalmente diferentes, por lo que no hay forma razonable de que implementes una "FOO".GetHashCode() insensible a mayúsculas y minúsculas en un mapa hash sensible a mayúsculas y minúsculas.

Sin embargo, puede crear un diccionario que no distinga entre mayúsculas y minúsculas al usar:

var comparer = StringComparer.OrdinalIgnoreCase; var caseInsensitiveDictionary = new Dictionary<string, int>(comparer);

O cree un nuevo diccionario insensible a mayúsculas y minúsculas con los contenidos de un diccionario existente que distingue entre mayúsculas y minúsculas (si está seguro de que no hay colisiones de casos):

var oldDictionary = ...; var comparer = StringComparer.OrdinalIgnoreCase; var newDictionary = new Dictionary<string, int>(oldDictionary, comparer);

Este diccionario luego usa la implementación GetHashCode() en StringComparer.OrdinalIgnoreCase manera que comparer.GetHashCode("foo") y comparer.GetHashcode("FOO") den el mismo valor.

Alternativamente, si solo hay unos pocos elementos en el diccionario y / o solo necesita buscar una o dos veces, puede tratar el diccionario original como un IEnumerable<KeyValuePair<TKey, TValue>> y simplemente iterar sobre él: -

var myKey = ...; var myDictionary = ...; var comparer = StringComparer.OrdinalIgnoreCase; var value = myDictionary.FirstOrDefault(x => String.Equals(x.Key, myKey, comparer))?.Value;

O si lo prefiere, sin el LINQ: -

var myKey = ...; var myDictionary = ...; var comparer = StringComparer.OrdinalIgnoreCase; int? value; foreach (var element in myDictionary) { if (String.Equals(element.Key, myKey, comparer)) { value = element.Value; break; } }

Esto le ahorra el costo de crear una nueva estructura de datos, pero a cambio el costo de una búsqueda es O (n) en lugar de O (1).


Para ti LINQers que nunca usan un constructor de diccionario regular:

myCollection.ToDictionary(x => x.PartNumber, x => x.PartDescription, StringComparer.OrdinalIgnoreCase)