primer acceso directo en trues rápidas y Falsas:
if(ReferenceEqual(actual, expected))
return true;
if(actual == null || expected == null || actual.Count != expected.Count)
return false;
Esto también maneja nulo comprobando así que todo lo demás que do no puede lanzar una excepción de referencia nula. Puede omitir toda esta barra comparando los recuentos si los tiene justo después de la creación como en su ejemplo, pero debe guardarlos si los pone en un método diferente, por si acaso.
No podemos simplemente llamar a SequenceEqual en los dos diccionarios, porque no tenemos la garantía de recuperar las claves en el mismo orden. Con otros tipos para el valor que podíamos hacer:
return actual.OrderBy(kvp => kvp.Key).SequenceEqual(expected.OrderBy(kvp => kvp.Key));
Pero esto no va a funcionar porque los dos valores de secuencia List<string>
-iguales no serán consideradas iguales al método DefaultEqualityComparer<List<string>>.Equals()
que esto va a poner en.
podríamos crear un IEqualityComparer<KeyValuePair<string, List<string>>>
si estábamos obligados-demonios en el uso de SequenceEqual, pero es probablemente más fácil de hacer el enfoque no LINQ, a pesar de que LINQ es normalmente más sencilla y concisa (una vez que encuentre la manera de hacerlo. Por lo tanto:..
List<string> expectedVal;
foreach(KeyValuePair<string, List<string> kvp in actual)
{
if(!expected.TryGetValue(kvp.key, out expectedVal) || kvp.Value.Count != expectedVal.Count || !kvp.Value.SequenceEquals(expectedVal))
return false;
}
return true;
variantes pueden tratar con diferentes puntos de vista de la igualdad Por ejemplo, podemos utilizar kvp.Value.OrderBy(x => x).SequenceEquals(expectedVal.OrderBy(x => x))
si quisiéramos considerar dos listas de los mismos artículos en diferentes órdenes como igual
en resumen, el mucho juntos:
if(ReferenceEqual(actual, expected))
return true;
if(actual == null || expected == null || actual.Count != expected.Count)
return false;
List<string> expectedVal;
foreach(KeyValuePair<string, List<string> kvp in actual)
{
if(!expected.TryGetValue(kvp.key, out expectedVal) || kvp.Value.Count != expectedVal.Count || !kvp.Value.SequenceEquals(expectedVal))
return false;
}
return true;
Editar: Sólo por diversión, la forma en que utiliza SequenceEquals:
internal class KvpSLSEq : IEqualityComparer<KeyValuePair<string, List<string>>>
{
public bool Equals(KeyValuePair<string, List<string>> x, KeyValuePair<string, List<string>> y)
{
return x.Key == y.Key && x.Value.Count == y.Value.Count && x.Value.SequenceEquals(y.Value);
}
public int GetHashCode(KeyValuePair<string, List<string>> obj)
{
//you could just throw NotImplementedException unless you'll reuse this elsewhere.
int hash = obj.Key.GetHashCode;
foreach(string val in obj.Value)
hash = hash * 31 + (val == null ? 0 : val.GetHashCode());
}
}
Este hecho se puede utilizar la concisa:
actual.OrderBy(kvp => kvp.Key).SequenceEqual(expected.OrderBy(kvp => kvp.Key), new KvpSLSEq());
pero es sólo muy concisa si KvpSLSEq se utiliza en otros lugares también.
¿Exige que los elementos de cada lista para estar en el mismo orden? – Rawling
No creo que haya un método integrado. Eche un vistazo aquí: http://stackoverflow.com/questions/3928822/comparing-2-dictionarystring-string-instances –
sí, todo debería ser el mismo, los mismos valores, mismo orden – user829174