Подтвердить что ты не робот

Когда использовать IEquatable<t> и почему

Что именно IEquatable<T> покупает вам? Единственная причина, по которой я вижу его полезность, заключается в создании универсального типа и принуждении пользователей к внедрению и написанию хорошего метода равенства.

Что мне не хватает?

4b9b3361

Ответ 1

Из MSDN:

Интерфейс IEquatable(T) используется объектами общей коллекции, такими как Dictionary(TKey, TValue), List(T) и LinkedList(T), при проверке на равенство в таких методах, как Contains, IndexOf, LastIndexOf и Remove.

Реализация IEquatable<T> потребует на один класс меньше для этих классов, и в результате будет немного быстрее, чем стандартный метод object.Equals, который был бы использован в противном случае. В качестве примера рассмотрим различную реализацию двух методов:

public bool Equals(T other) 
{
  if (other == null) 
     return false;

  return (this.Id == other.Id);
}

public override bool Equals(Object obj)
{
  if (obj == null) 
     return false;

  T tObj = obj as T;  // The extra cast
  if (tObj == null)
     return false;
  else   
     return this.Id == tObj.Id;
}

Ответ 2

Я поражен тем, что здесь не упоминается самая важная причина.

IEquatable<> был введен главным образом для структур по двум причинам:

  • Для типов значений (read structs) для нестандартного Equals(object) требуется бокс. IEquatable<> позволяет структуре реализовать строго типизированный метод Equals, чтобы не требовался бокс.

  • Для structs реализация по умолчанию Object.Equals(Object) (которая является переопределенной версией в System.ValueType) выполняет проверку равенства значений с помощью отражения для сравнения значений каждого поля в типе. Когда исполнитель переопределяет виртуальный метод Equals в структуре, цель состоит в том, чтобы предоставить более эффективные средства для выполнения проверки равенства значений и, возможно, основывать сравнение на некотором подмножестве поля или свойств структуры.

Оба улучшают производительность.

Типы ссылок (классы чтения) не так полезны. Реализация IEquatable<> позволяет вам избегать приведения из System.Object, но это очень тривиальный выигрыш. Мне все еще нравится IEquatable<> для моих классов, поскольку он логически делает намерение явным.

Ответ 3

Я использую IEquatable<T> довольно часто, хотя с чисто технической точки зрения он не дает мне особых преимуществ. Переопределение System.Object.Equals может предоставить вам ту же функциональность.

Однако мне нравится явная реализации IEquatable<T>. Я довольно часто использую понятия сущностей и объектов-значений из доменного дизайна, и использую IEquatable<T>, в частности, для объектов-значений, просто потому, что он сигнализирует что тип имеет четко определенное равенство.

Ответ 4

В дополнение к другим ответам здесь очень хорошая причина для реализации IEquatable<T> (и, очевидно, переопределения Equals(object)) для типов значений. Просто посмотрите на код ValueType.Equals(object) по умолчанию, который вызывается иначе. Это абсолютный убийца производительности, который вводит бокс, оценивает тип и, наконец, возвращается к отражению, если какое-либо из полей является ссылочными типами.

public override bool Equals(object obj)
{
    if (obj == null)
    {
        return false;
    }
    RuntimeType type = (RuntimeType) base.GetType();
    RuntimeType type2 = (RuntimeType) obj.GetType();
    if (type2 != type)
    {
        return false;
    }
    object a = this;
    if (CanCompareBits(this))
    {
        return FastEqualsCheck(a, obj);
    }
    FieldInfo[] fields = type.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
    for (int i = 0; i < fields.Length; i++)
    {
        object obj3 = ((RtFieldInfo) fields[i]).UnsafeGetValue(a);
        object obj4 = ((RtFieldInfo) fields[i]).UnsafeGetValue(obj);
        if (obj3 == null)
        {
            if (obj4 != null)
            {
                return false;
            }
        }
        else if (!obj3.Equals(obj4))
        {
            return false;
        }
    }
    return true;
}

В некоторых сценариях (таких как использование типа значения в качестве ключа в словаре) он может убить производительность одним мазком.