Структура с одним полем (то есть целое число) - вам все еще нужно переопределить GetHashCode, Equals и т. Д.? - PullRequest
0 голосов
/ 04 октября 2018

Часто, когда кто-то говорит о структурах, рекомендуется переопределить Equals, GetHashCode и т. Д.

Обязательно ли это, если у вас есть struct всего с одно целое число (или любой другой простой тип значения )?

Скажите, например:

public struct LolCatId
{
    public int Id { get; }

    public LolCatId(int id)
    {
        Id = id;
    }
}

При использовании в HashSets и т. д. - есть что-нибудьоб этом нужно думать, или это будет работать идеально, как вы ожидаете во всех случаях с точки зрения производительности?

1 Ответ

0 голосов
/ 04 октября 2018

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

И некоторые реализации по умолчанию Equals весьма странные , например:

  // Wrong Equals optimization demo: 
  // .Net (4.7) doesn't use reflection here but compare bytes 
  // and this decision is incorrect in the context
  struct MyDemo {
    public double x;
  }

...

  byte[] bits = BitConverter.GetBytes(double.NaN);

  bits[1] = 42;

  // a holds "standard" NaN
  MyDemo a = new MyDemo() { x = double.NaN };
  // b holds "modified" NaN
  MyDemo b = new MyDemo() { x = BitConverter.ToDouble(bits, 0)};

  Console.Write(string.Join(Environment.NewLine, 
    $"Are structs equal? {(a.Equals(b) ? "Yes" : "No")}",
    $"Are fields equal?  {(a.x.Equals(b.x) ? "Yes" : "No")}"));

Результат:

Are structs equal? No
Are fields equal?  Yes

Подробнее см.

https://blogs.msdn.microsoft.com/seteplia/2018/07/17/performance-implications-of-default-struct-equality-in-c/

Давайте будем на безопасной стороне , особенно когда оба метода легко могут быть реализовано , например, в вашем случае:

public struct LolCatId {
  public int Id { get; }

  public LolCatId(int id) {
    Id = id;
  }

  public override int GetHashCode() => Id;

  public override bool Equals(object obj) => 
    obj is LolCatId other ? other.Id == Id : false;
}
...