需要在结构中重写什么以确保平等运行正常?
正如标题所说:我是否需要重写==
运算符? 那么.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/