正如标题所说: 我需要覆盖 ==操作符吗? .Equals()方法怎么样? 我遗漏了什么吗?
==
.Equals()
来自 msdn 的示例
public struct Complex { double re, im; public override bool Equals(Object obj) { return obj is Complex c && this == c; } 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); } }
两者之间的基本区别在于,==操作符是静态的,也就是说,要调用的适当方法是在编译时确定的,而 Equals方法是在实例上动态调用的。 定义这两个结构可能是最好的办法,即使对于结构来说这没有那么重要,因为结构不能被扩展(一个结构不能从另一个结构继承)。
Equals
你也应该实现 IEqutable < T > ,这里是框架设计指南的摘录:
在值类型上实现 IEqutable。 值类型上的 Object.Equals 方法导致装箱,而其 默认实现的效率不是很高,因为它使用了反射。 平等可以提供更好的性能 实现,以便它不会导致装箱。
public struct Int32 : IEquatable<Int32> { public bool Equals(Int32 other){ ... } }
请遵循与... ... 相同的指导方针 重写对象。等于当 实现了等式,等于。 有关详细信息,请参阅8.7.1节 关于重写对象的指导原则
不幸的是,我没有足够的声誉来评论其他条目。因此,我张贴可能的增强顶级解决方案在这里。
如果我错了,请纠正我,但上面提到的实现
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 是对称的,所以复杂(2,1)和复杂(1,2)会产生相同的 hashCode。
我们也许应该做些类似的东西:
public override int GetHashCode() { return re.GetHashCode() * 17 ^ im.GetHashCode(); }
为了完整起见,我还建议重载 Equals方法:
public bool Equals(Complex other) { return other.re == re && other.im == im; }
这是一个真正的速度改进,因为 Equals(Object obj)方法的输入参数没有装箱
Equals(Object obj)
使用值类型的一些最佳实践:
这来自这篇文章: http://theburningmonk.com/2015/07/beware-of-implicit-boxing-of-value-types/
大多数情况下,您可以避免使用 structs 实现 Equals 和 GetHashcode-因为编译器会自动实现 Value 类型,对引用成员使用按位内容 + 反射。
看看这个帖子: 对于数据存储结构/类,哪种方式最好?
因此,为了方便使用,您仍然可以实现 = = 和! = 。
但是在大多数情况下,您可以避免实现 Equals 和 GetHashcode。 必须实现 Equals 和 GetHashCode 的情况是针对一个不希望考虑的字段。 例如,一个字段随着时间的推移而变化,比如“人的年龄”或“汽车的速度”(如果你想在同一个地方在字典里找到它,那么物体的标识就不应该改变)
问候,最好的暗号