Jon Skeet ya dio una buena explicación.
Sin embargo, si todo lo que (o cualquier otra persona que lee esta pregunta) quieren es un método eficaz para la comparación de los diccionarios que aquí hay una simple extensión a base de LINQ que va a hacer precisamente eso:
/// <summary>
/// Compares two dictionaries for equality.
/// </summary>
/// <returns>
/// True if the dictionaries have equal contents or are both null, otherwise false.
/// </returns>
public static bool DictionaryEqual<TKey, TValue>(
this IDictionary<TKey, TValue> dict1, IDictionary<TKey, TValue> dict2,
IEqualityComparer<TValue> equalityComparer = null)
{
if (dict1 == dict2)
return true;
if (dict1 == null | dict2 == null)
return false;
if (dict1.Count != dict2.Count)
return false;
if (equalityComparer == null)
equalityComparer = EqualityComparer<TValue>.Default;
return dict1.All(kvp =>
{
TValue value2;
return dict2.TryGetValue(kvp.Key, out value2)
&& equalityComparer.Equals(kvp.Value, value2);
});
}
lo hace tal vez parecen un Un poco esponjoso, pero quería buena legibilidad (y pruebas nulas).
Así que si lo que quieres es un "one-liner" y ustedes ya saben que los dos diccionarios son no nulo y que el tipo TValue
anula el método Equals correctamente, entonces sólo se necesita realmente esta cantidad (sans las nulos comprueba si TValue
es un valuetype por supuesto):
bool isEqual = dict1.Count == dict2.Count && dict1.All(kvp =>
{
TValue value2;
return dict2.TryGetValue(kvp.Key, out value2)
&& (kvp.Value == null ? value2 == null : kvp.Value.Equals(value2));
});
Si usted quiere hacer una comparación en los diccionarios no tiene por qué tener el mismo tipo de valor, o si prefiere utilizar una expresión delegada o lambda en lugar de tener que implementar un IEqualityComparer, esta extensión En su lugar, hará el truco para usted:
/// <summary>
/// Compares two dictionaries for equality using a custom value equality function.
/// </summary>
/// <returns>
/// True if both dictionaries are null or both have the same set of keys and comparing
/// their respective values for each key using the <paramref name="valueEqualityFunc"/>
/// returns true, otherwise false.
/// </returns>
public static bool DictionaryEqual<TKey, TValue1, TValue2>(
this IDictionary<TKey, TValue1> dict1, IDictionary<TKey, TValue2> dict2,
Func<TValue1, TValue2, bool> valueEqualityFunc)
{
if (valueEqualityFunc == null)
throw new ArgumentNullException("valueEqualityFunc");
if (dict1 == dict2)
return true;
if (dict1 == null | dict2 == null)
return false;
if (dict1.Count != dict2.Count)
return false;
return dict1.All(kvp =>
{
TValue2 value2;
return dict2.TryGetValue(kvp.Key, out value2)
&& valueEqualityFunc(kvp.Value, value2);
});
}
Como puede ver, es casi lo mismo que antes.
Aquí está un ejemplo de uso:
var d1 = new Dictionary<string, string>();
var d2 = new Dictionary<string, string>();
d1.Add("key1", "dog");
d2.Add("key1", "Dog");
d1.Add("key2", "CAT");
d2.Add("key2", "cat");
bool isEqual = DictionaryEqual(d1, d2,
(s1, s2) => string.Equals(s1, s2, StringComparison.OrdinalIgnoreCase));
Si ejecuta el código anterior isEqual
llegará a ser verdad.
"Los objetos ICustomeInterface anulan el método Equals correctamente". ¿Eso incluye una anulación constante para 'GetHashCode()'?No estoy seguro si es relevante aquí, pero un 'GetHashCode()' roto es uno de los problemas más comunes con las comparaciones de igualdad. – CodesInChaos
¿Cuál es el tipo subyacente? ¿Es un tipo de valor o un tipo de referencia? – Tipx
Tienes una contradicción en tu publicación. Usted declara que tiene "dos diccionarios ordenados" pero, por otro lado, declara que usa 'Dictionary', que está desordenado. –
CodesInChaos