需要在结构中重写什么以确保平等运行正常?

正如标题所说:我是否需要重写==运算符? 那么.Equals()方法呢? 任何我失踪?

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

你也应该实现IEquatable <T>。 以下是框架devise指南摘录:

在值types上实现IEquatable。 值types的Object.Equals方法会导致装箱,而且它的默认实现不是很有效率,因为它使用了reflection。 IEquatable.Equals可以提供更好的性能,并且可以实现,以便它不会导致拳击。

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

遵循与实现IEquatable.Equals时重写Object.Equals一样的原则。 有关覆盖Object.Equals的详细指导,请参见第8.7.1节

不幸的是,我没有足够的声望评论其他条目。 所以我在这里发布可能的增强的顶级解决scheme。

纠正我,如果我错了,但上面提到的实现

 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)会给出相同的hashCode。

我们可能应该更像是:

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

大多数情况下,您可以避免在结构中实现Equals和GetHashcode – 因为编译器会为值types使用按位内容+reflection作为引用成员的自动实现。

看看那个post: 哪个最适合数据存储结构/类?

所以为了便于使用,您仍然可以实现==和!=。

但是大多数时候你可以避免实现Equals和GetHashcode。
一个你不得不实现Equals和GetHashCode的情况是你不想考虑的一个字段。
例如,随着时间的推移,像人的年龄或汽车的瞬间速度一样的字段(如果你想在同一地点的字典中find它,对象的身份不应该改变)

问候,最好的代码

这两者之间的基本区别在于==运算符是静态的,即在编译时确定适当的调用方法,而在实例上则调用Equals方法。
定义两者可能是最好的事情,即使在结构体的情况下,这个问题也不是那么重要,因为结构体不能被扩展(一个结构体不能从另一个结构体inheritance)。

只是为了completet我也会build议重载Equals方法:

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

这是一个真正的改进,因为Equals(Object obj)方法的input参数没有发生装箱

一些使用值types的最佳实践:

  • 使他们不变
  • 重写Equals(将对象作为参数的那个);
  • 超载等于取另一个相同值types的实例(例如* Equals(Complex other));
  • 重载运算符==和!=;
  • 重载GetHashCode

这来自这个职位: http : //theburningmonk.com/2015/07/beware-of-implicit-boxing-of-value-types/