正如标题所说:我需要覆盖==
操作员吗?方法怎么样.Equals()
?有什么我想念的吗?
6 回答
来自 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);
}
}
您还应该实现 IEquatable<T>。以下是框架设计指南的摘录:
请在值类型上实现 IEquatable。值类型上的 Object.Equals 方法会导致装箱,并且它的默认实现不是很有效,因为它使用了反射。IEquatable.Equals 可以提供更好的性能,并且可以实施,这样它就不会导致装箱。
public struct Int32 : IEquatable<Int32> {
public bool Equals(Int32 other){ ... }
}
在实现 IEquatable.Equals 时,请遵循与覆盖 Object.Equals 相同的准则。有关覆盖 Object.Equals 的详细指南,请参阅第 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 是对称的,所以 Complex(2,1) 和 Complex(1,2) 会给出相同的 hashCode。
我们可能应该做一些更像:
public override int GetHashCode()
{
return re.GetHashCode() * 17 ^ im.GetHashCode();
}
大多数情况下,您可以避免在结构中实现 Equals 和 GetHashcode - 因为编译器使用按位内容 + 反射作为引用成员的值类型自动实现。
看看那个帖子: 哪个最适合数据存储结构/类?
因此,为了便于使用,您仍然可以实现 == 和 !=。
但大多数时候你可以避免实现 Equals 和 GetHashcode。
您必须实现 Equals 和 GetHashCode 的情况是针对您不想考虑的字段。
例如,随着时间的推移而变化的字段,例如人的年龄或汽车的即时速度(如果您想在字典中的同一位置找到它,则对象的身份不应该改变)
问候,最好的代码
两者的基本区别在于==
操作符是静态的,即调用的适当方法是在编译时确定的,而Equals
方法是在实例上动态调用的。
定义两者可能是最好的做法,即使这在结构的情况下不那么重要,因为结构不能扩展(一个结构不能从另一个继承)。
为了完整起见,我还建议重载Equals
方法:
public bool Equals(Complex other)
{
return other.re == re && other.im == im;
}
Equals(Object obj)
这是一个真正的快速改进,因为方法的输入参数没有发生装箱
使用值类型的一些最佳实践:
- 使它们不可变
- 覆盖 Equals(将对象作为参数的那个);
- 重载 Equals 以获取相同值类型的另一个实例(例如 * Equals(Complex other));
- 重载运算符 == 和 !=;
- 覆盖 GetHashCode
这来自这篇文章:http ://theburningmonk.com/2015/07/beware-of-implicit-boxing-of-value-types/