C# 需要在结构中覆盖哪些内容以确保平等正常运行?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1502451/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What needs to be overridden in a struct to ensure equality operates properly?
提问by RCIX
As the title says: do I need to override the ==
operator? how about the .Equals()
method? Anything I'm missing?
正如标题所说:我需要覆盖==
运算符吗?怎么样的.Equals()
方法?我缺少什么吗?
采纳答案by UpTheCreek
An example from msdn
来自 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);
}
}
回答by Paolo Tedesco
The basic difference among the two is that the ==
operator is static, i.e. the appropriate method to invoke is determined at compile time, while the Equals
method is invoked dinamically on an instance.
Defining both is probably the best thing to do, even if this matters less in the case of structs, since structs cannot be extended (a struct can't inherit from another).
两者的基本区别在于==
操作符是静态的,即在编译时确定要调用的适当方法,而在Equals
实例上动态调用该方法。
定义两者可能是最好的做法,即使这在结构体的情况下不那么重要,因为结构体不能被扩展(一个结构体不能从另一个结构体继承)。
回答by Dzmitry Huba
You should also implement IEquatable<T>. Here is an excerpt from Framework Design Guidelines:
您还应该实现 IEquatable<T>。以下是框架设计指南的摘录:
DO implement IEquatable on value types. The Object.Equals method on value types causes boxing, and its default implementation is not very effcient because it uses refection. IEquatable.Equals can offer much better performance and can be implemented so that it does not cause boxing.
务必在值类型上实现 IEquatable。值类型上的 Object.Equals 方法会导致装箱,并且它的默认实现不是很有效,因为它使用了反射。IEquatable.Equals 可以提供更好的性能,并且可以实现以使其不会导致装箱。
public struct Int32 : IEquatable<Int32> {
public bool Equals(Int32 other){ ... }
}
DO follow the same guidelines as for overriding Object.Equals when implementing IEquatable.Equals. See section 8.7.1 for detailed guidelines on overriding Object.Equals
在实现 IEquatable.Equals 时,务必遵循与覆盖 Object.Equals 相同的准则。有关覆盖 Object.Equals 的详细指南,请参阅第 8.7.1 节
回答by Ajk
Unfortunetely I don't have enough reputation to comment other entries. So I'm posting possible enhancement to the top solution here.
不幸的是,我没有足够的声誉来评论其他条目。所以我在这里发布了对顶级解决方案的可能增强功能。
Correct me, if i'm wrong, but implementation mentioned above
纠正我,如果我错了,但上面提到的实现
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);
}
}
Has major flaw. I'm refering to
有重大缺陷。我指的是
public override int GetHashCode()
{
return re.GetHashCode() ^ im.GetHashCode();
}
XORing is symmetrical, so Complex(2,1) and Complex(1,2) would give same hashCode.
XORing 是对称的,所以 Complex(2,1) 和 Complex(1,2) 会给出相同的 hashCode。
We should probably make something more like:
我们可能应该做一些更像:
public override int GetHashCode()
{
return re.GetHashCode() * 17 ^ im.GetHashCode();
}
回答by Tomasz Jaskuλa
Just for completness I would also advice to overload Equals
method:
只是为了完整性,我还建议重载Equals
方法:
public bool Equals(Complex other)
{
return other.re == re && other.im == im;
}
this is a real spead improvement as there is no boxing occuring of the input argument of Equals(Object obj)
method
这是一个真正的速度改进,因为Equals(Object obj)
方法的输入参数没有发生装箱
Some best prac-tices for using value types:
使用值类型的一些最佳实践:
- make them immutable
- over-ride Equals (the one that takes an object as argument);
- over-load Equals to take another instance of the same value type (e.g. * Equals(Complex other));
- over-load oper-a-tors == and !=;
- over-ride GetHashCode
- 使它们不可变
- 覆盖 Equals(将对象作为参数的那个);
- 重载 Equals 以采用相同值类型的另一个实例(例如 * Equals(Complex other));
- 重载运算符 == 和 !=;
- 覆盖 GetHashCode
This comes from this post: http://theburningmonk.com/2015/07/beware-of-implicit-boxing-of-value-types/
这来自这篇文章:http: //theburningmonk.com/2015/07/beware-of-implicit-boxing-of-value-types/
回答by Emmanuel DURIN
Most of the time you can avoid implementing Equals and GetHashcode in structs - because there is an automatic implementation by the compiler for Value types using bitwise content + reflection for reference members.
大多数情况下,您可以避免在结构中实现 Equals 和 GetHashcode - 因为编译器会自动实现对引用成员使用按位内容 + 反射的值类型。
Have a look at that post : Which is best for data store Struct/Classes?
看看那个帖子: 哪个最适合数据存储结构/类?
So for ease of use you could still implement == and !=.
因此,为了便于使用,您仍然可以实现 == 和 !=。
But most of the time you can avoid implementing Equals and GetHashcode.
A case where you'd have to implement Equals and GetHashCode is for a field that you don't wan't to take into account.
For instance a field that varies as time goes by like Age of a Person or instantSpeed of a car( the identity of the object shouldn't change if you want to find it back in the dictionary at the same place)
但大多数情况下,您可以避免实现 Equals 和 GetHashcode。
您必须实现 Equals 和 GetHashCode 的情况是您不想考虑的字段。
例如,随着时间的推移而变化的字段,例如一个人的年龄或汽车的即时速度(如果您想在字典中的同一位置找到它,则对象的身份不应该改变)
Regards, best code
问候,最好的代码