Pregunta

Estoy intentando comparar el tipo personalizado en dos List<T> y usar el Intersect / Except método.La igualdad está determinada por tres campos de este tipo.La igualdad se basa en algo más que la condición ordinaria (todos los campos contienen los mismos datos).Implementé por supuesto el IEqualityComparer<T>.Mi problema es que el GetHashCode() El método devuelve no es igual una vez que el hashCode no es el mismo y esto no me ayuda ya que esto no es cierto en mi caso.

¿Hay alguna forma de comparar dos objetos personalizados cuando la igualdad se basa en más de una condición para poder usar intersección/excepto/distinción, etc.?

Aquí está mi código:

public bool Equals(ComparableObject x, ComparableObject y)
{
    if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
        return false;

    if (Object.ReferenceEquals(x, y))
        return true;

    if (x.Var1.Equals(y.Var1) && x.Var3.Equals(y.Var3) && !x.Var2.Equals(y.Var2))
        return false;

    if (x.Var1.Equals(y.Var1) && !x.Var3.Equals(y.Var3) && !x.Var2.Equals(y.Var2))
        return true;


    if (!x.Var1.Equals(y.Var1) && x.Var3.Equals(y.Var3) && !x.Var2.Equals(y.Var2))
        return false;

    if (!x.Var1.Equals(y.Var1) && x.Var3.Equals(y.Var3) && x.Var2.Equals(y.Var2))
        return true;

    if (x.Var1.Equals(y.Var1) && !x.Var3.Equals(y.Var3) && x.Var2.Equals(y.Var2))
        return false;

    if (!x.Var1.Equals(y.Var1) && !x.Var3.Equals(y.Var3) && x.Var2.Equals(y.Var2))
        return false;

    if (!x.Var1.Equals(y.Var1) && !x.Var3.Equals(y.Var3) && !x.Var2.Equals(y.Var2))
        return false;


    return x.Var1.Equals(y.Var1) && x.Var1.Equals(y.Var1) && x.Var3.Equals(y.Var3);
}


public int GetHashCode(ComparableObject x)
{
    return obj.Var1.GetHashCode() ^ obj.Var2.GetHashCode()^ obj.Var3.GetHashCode()
}
¿Fue útil?

Solución

Es su trabajo proporcionar tal GetHashCode() que el valor que devuelve será diferente para los objetos que son diferente (en tantos casos como sea posible;aún puede devolver el mismo código hash para objetos no iguales), y siempre será el mismo para objetos que puede ser iguales (en todos los casos;no puede devolver códigos hash diferentes para objetos iguales).

Por ejemplo, si uno de los tres campos que compara es un int, puedes devolver ese campo como GetHashCode().

Sin embargo, si le resulta difícil encontrar algo inteligente, puede devolver una constante, como por ejemplo 42.Por aquí Equals() Se llamará para todos los pares de objetos, entregando los resultados esperados, aunque de la manera menos eficiente.

Otros consejos

No estoy seguro de si tiene otros problemas con GetHashCode en sus tipos subyacentes, pero este es un ejemplo de un tipo personalizado y un IEqualityComparer que devuelve verdadero si solo los dos primeros campos son iguales.Esto permitira Except etc.para trabajar en el tipo.

    public class CustomType
    {
        public int Val1 { get; set; }
        public int Val2 { get; set; }
        public int Val3 { get; set; }
    }

    class CustomTypeComparer : IEqualityComparer<CustomType>
    {
        public bool Equals(CustomType x, CustomType y)
        { return x.Val1 == y.Val1 && x.Val2 == y.Val2; }

        public int GetHashCode(CustomType obj)
        { return obj.Val1.GetHashCode() ^ obj.Val2.GetHashCode(); }
    }

Si sus propiedades no son tipos simples como int, es posible que desee utilizar Equals() en lugar de == para comparar los objetos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top