Вопрос

Я пытаюсь сравнить пользовательский тип в двух List<T> и используйте Intersect / Except метод.Равенство определяется тремя полями этого типа.Равенство основано на более чем обычном условии (все поля содержат одни и те же данные).Я реализовал, конечно, IEqualityComparer<T>.Моя проблема в том, что GetHashCode() метод возвращает не равно, если хеш-код не тот, и это мне не помогает, поскольку в моем случае это не так.

Есть ли способ сравнить два пользовательских объекта, когда равенство основано на более чем одном условии, чтобы я мог использовать пересечение/исключение/отличие и т. д....?

Вот мой код:

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()
}
Это было полезно?

Решение

Ваша задача – обеспечить такое GetHashCode() что возвращаемое значение будет различным для объектов, которые являются разные (в как можно большем количестве случаев;вы по-прежнему можете возвращать один и тот же хэш-код для неравных объектов), и он всегда будет одинаковым для объектов, которые может быть равными (во всех случаях;вы не можете возвращать разные хеш-коды для одинаковых объектов).

Например, если одно из трех сравниваемых полей является int, вы можете вернуть это поле как GetHashCode().

Если же сложно придумать что-то умное, можно вернуть константу, например 42.Сюда Equals() будет вызываться для всех пар объектов, обеспечивая ожидаемые результаты, хотя и с наименьшей производительностью.

Другие советы

Не уверен, есть ли у вас другие проблемы с GetHashCode в ваших базовых типах, но это пример пользовательского типа и IEqualityComparer, который возвращает true, если только первые два поля одинаковы.Это позволит Except и т. д.работать над типом.

    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(); }
    }

Если ваши свойства не являются простыми типами, как int, вы можете использовать Equals() вместо == сравнивать объекты.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top