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

Что нужно переопределить в структуре, чтобы обеспечить правильное функционирование равенства?

Как говорится в заголовке: нужно ли переопределить оператор ==? как насчет метода .Equals()? Что-нибудь мне не хватает?

4b9b3361

Ответ 1

Пример из msdn

public struct Complex 
{
   double re, im;
   public override bool Equals(Object obj) 
   {
      return obj is Complex && this == (Complex)obj;
   }
   public override int GetHashCode() 
   {
      return re.GetHashCode() ^ im.GetHashCode();
   }
   public static bool operator ==(Complex x, Complex y) 
   {
      return x.re == y.re && x.im == y.im;
   }
   public static bool operator !=(Complex x, Complex y) 
   {
      return !(x == y);
   }
}

Ответ 2

Вы также должны реализовать IEquatable <T> . Вот выдержка из Руководства по дизайну каркаса:

DO реализует IEquatable для типов значений. Метод Object.Equals для типов значений вызывает бокс и его реализация по умолчанию не очень эффективна, поскольку использует рефлексию. IEquatable.Equals могут предложить гораздо лучшую производительность и могут быть реализован так, чтобы он не вызывал бокса.

public struct Int32 : IEquatable<Int32> {
    public bool Equals(Int32 other){ ... }
}

DO следует тем же рекомендациям, что и для переопределение Object.Equals, когда реализация IEquatable.Equals. См. Раздел 8.7.1 для подробного рекомендации по переопределению Object.Equals

Ответ 3

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

Исправьте меня, если я ошибаюсь, но реализация упомянута выше

public struct Complex 
{
   double re, im;
   public override bool Equals(Object obj) 
   {
      return obj is Complex && this == (Complex)obj;
   }
   public override int GetHashCode() 
   {
      return re.GetHashCode() ^ im.GetHashCode();
   }
   public static bool operator ==(Complex x, Complex y) 
   {
      return x.re == y.re && x.im == y.im;
   }
   public static bool operator !=(Complex x, Complex y) 
   {
      return !(x == y);
   }
}

Имеет большой недостаток. Я имею в виду

  public override int GetHashCode() 
   {
      return re.GetHashCode() ^ im.GetHashCode();
   }

XORing симметричен, поэтому Complex (2,1) и Complex (1,2) будут давать одинаковый хэш-код.

Мы должны, вероятно, сделать что-то большее:

  public override int GetHashCode() 
   {
      return re.GetHashCode() * 17 ^ im.GetHashCode();
   }

Ответ 4

В большинстве случаев вы можете избежать реализации Equals и GetHashcode в structs - потому что существует автоматическая реализация компилятором для типов Value с использованием поразрядного контента + отражение для ссылочных элементов.

Взгляните на этот пост: Что лучше для хранилища данных Struct/Classes?

Поэтому для удобства использования вы все равно можете реализовать == и! =.

Но большую часть времени вы можете избежать использования Equals и GetHashcode.
Случай, когда вам нужно реализовать Equals и GetHashCode, - это поле, которое вы не должны принимать во внимание.
Например, поле, которое меняется с течением времени, как Age of Person или instantSpeed ​​автомобиля (идентификация объекта не должна изменяться, если вы хотите найти его обратно в словаре в том же месте)

С уважением, лучший код

Ответ 5

Основное различие между ними состоит в том, что оператор == является статическим, то есть соответствующий метод для вызова определяется во время компиляции, тогда как метод Equals вызывается динамически на экземпляре.
Определение обоих, вероятно, лучше всего делать, даже если это имеет меньшее значение в случае структур, поскольку структуры не могут быть расширены (структура не может наследовать от другой).

Ответ 6

Просто для полноты я также советю перегрузить метод Equals:

public bool Equals(Complex other) 
{
   return other.re == re && other.im == im;
}

это реальное улучшение речи, так как нет бокса при вводе аргумента метода Equals(Object obj)

Некоторые рекомендации по использованию типов значений:

  • сделать их неизменными
  • override Equals (тот, который принимает объект как аргумент); Перегрузка
  • Равно как и другой экземпляр одного и того же типа значений (например, * Equals (Complex other));
  • операторы перегрузки == и! =;
  • переопределить GetHashCode

Это происходит из этого сообщения: http://theburningmonk.com/2015/07/beware-of-implicit-boxing-of-value-types/