using System.Collections.Generic;
using System.Linq;
namespace YourProject.Extensions
{
public static class ListExtensions
{
public static bool SetwiseEquivalentTo<T>(this List<T> list, List<T> other)
where T: IEquatable<T>
{
if (list.Except(other).Any())
return false;
if (other.Except(list).Any())
return false;
return true;
}
}
}
Às vezes, você só precisa saber se duas listas são diferentes, e não quais são essas diferenças. Nesse caso, considere adicionar esse método de extensão ao seu projeto. Observe que seus objetos listados devem implementar o IEquatable!
Uso:
public sealed class Car : IEquatable<Car>
{
public Price Price { get; }
public List<Component> Components { get; }
...
public override bool Equals(object obj)
=> obj is Car other && Equals(other);
public bool Equals(Car other)
=> Price == other.Price
&& Components.SetwiseEquivalentTo(other.Components);
public override int GetHashCode()
=> Components.Aggregate(
Price.GetHashCode(),
(code, next) => code ^ next.GetHashCode()); // Bitwise XOR
}
Qualquer que seja a Component
classe, os métodos mostrados aqui Car
devem ser implementados quase de forma idêntica.
É muito importante observar como escrevemos GetHashCode. Para implementar corretamente IEquatable
, Equals
e GetHashCode
deve operar nas propriedades da instância de uma maneira logicamente compatível.
Duas listas com o mesmo conteúdo ainda são objetos diferentes e produzirão códigos de hash diferentes. Como queremos que essas duas listas sejam tratadas como iguais, devemos GetHashCode
produzir o mesmo valor para cada uma delas. Podemos fazer isso delegando o código de hash a todos os elementos da lista e usando o XOR bit a bit padrão para combiná-los todos. O XOR é independente de ordem, portanto, não importa se as listas são classificadas de maneira diferente. É importante apenas que eles contenham apenas membros equivalentes.
Nota: o nome estranho é implicar o fato de que o método não considera a ordem dos elementos na lista. Se você se importa com a ordem dos elementos na lista, esse método não é para você!