IEquatable, как правильно реализовать это - PullRequest
1 голос
/ 09 января 2012

Я использую .net 2.0 и c #, и я реализовал интерфейс IEquatible в своем классе следующим образом: -

public MyClass() :  IEquatable<MyClass>
{
    Guid m_id = Guid.NewGuid();

    public Guid Id
    {
        get
        {
            return m_id;
        }
    }

    #region IEquatable<MyClass> Members

    public bool Equals(MyClass other)
    {
        if (this.Id == other.Id)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    #endregion
}

Это плохая практика программирования? Я читал, что мне также нужно реализовать Object.Equals и Object.GetHashCode, но я не уверен, почему.

Я хочу иметь возможность проверить, что экземпляр MyClass еще не содержится в общем списке типа MyClass. Почему фреймворк только предполагает, что вы используете только Равные?

Любая помощь будет принята с благодарностью.

Ответы [ 2 ]

2 голосов
/ 09 января 2012

Вы можете проверить, содержит ли ваш список элемент, используя пользовательский предикат для критериев, используя LINQ.В этом случае вам не нужно переопределять Equals и не реализовывать IEquatable:

// check if the list contains an item with a specific ID
bool found = someList.Any(item => item.ID == someId);

Переопределять EqualsGetHashCode), а реализация IEquatable полезна, если вам необходимо сохранитьваш товар в Dictionary или Hashtable.

0 голосов
/ 17 декабря 2012

Это плохая практика программирования?

Реализация IEquatable<T> - это замечательно, даже в большей степени для структур, но просто сделать это недостаточно.

Я читал, что мне также нужно реализовать Object.Equals

Прочитайте здесь, почему ..

и Object.GetHashCode, но я не уверен, почему.

Прочтите здесь и здесь . Серьезно, они обсуждались очень много раз, и это довольно просто. Короче, вам это нужно для типов коллекций, которые имеют дело с хешами, такими как Dictionary<,> или HashSet<>

Я хочу иметь возможность проверить, что экземпляр MyClass еще не содержится в общем списке типа MyClass. Почему фреймворк только предполагает, что вы используете только Равные?

Зависит от типа коллекции. Для List<T> он будет проверять равенство только на основании того, как вы определили метод Equals, скажем для метода Contains. Для большинства сценариев вам понадобится только Equals. Но если у вас есть HashSet<T>, то проверки отсутствия и присутствия будут использовать хэш ваших объектов. Framework действительно просит нас реализовать хорошие подходы к хешированию (без повторного изобретения колеса) в соответствующих местах .

Любая помощь будет принята с благодарностью.

Сделайте, как показано ниже, но вы должны перегружать операторы == и !=, только если это имеет смысл для вас. Увидев ваш класс, я предположил, что нормально иметь семантику значений для вашего класса. В противном случае просто игнорируйте эту часть (если == должно означать равенство ссылок) ... Достаточно получить хеш-код из вашего guid, при условии, что это все, что вам нужно для проверки равенства.

public sealed class MyClass : IEquatable<MyClass>
{
    Guid m_id = Guid.NewGuid();

    public Guid Id { get { return m_id; } }

    public bool Equals(MyClass other)
    {
        if (ReferenceEquals(this, other))
            return true;

        if (ReferenceEquals(null, other))
            return false;

        return Id == other.Id; 
    }

    public override bool Equals(object obj)
    {
        return Equals(obj as MyClass);
    }

    public static bool operator ==(MyClass lhs, MyClass rhs)
    {
        if (ReferenceEquals(lhs, null))
            return ReferenceEquals(rhs, null);

        return lhs.Equals(rhs);
    }

    public static bool operator !=(MyClass lhs, MyClass rhs)
    {
        return !(lhs == rhs);
    }

    public override int GetHashCode()
    {
        return Id.GetHashCode();
    }   
}

Чтобы не ошибиться, используйте фрагмент здесь : Для хорошего обзора см. Эту ветку SO.

...