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

时间:2009-10-01 07:43:08

标签: c# .net struct operators equals-operator

正如标题所说:我是否需要覆盖==运算符? .Equals()方法怎么样?我缺少什么?

6 个答案:

答案 0 :(得分:80)

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

答案 1 :(得分:43)

您还应该实现IEquatable< T>。以下是框架设计指南的摘录:

  

在值类型上实现IEquatable。   值类型的Object.Equals方法导致装箱,以及它   默认实现效率不高,因为它使用了反射。   IEquatable.Equals可以提供更好的性能   实施,以免它导致拳击。

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

请遵循相同的指导原则   覆盖Object.Equals时   实现IEquatable.Equals。   有关详细信息,请参见第8.7.1节   重写Object.Equals的指南

答案 2 :(得分:14)

不幸的是,我没有足够的声誉评论其他参赛作品。所以我在这里发布了对顶级解决方案的可能增强。

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

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

答案 3 :(得分:9)

大多数情况下,您可以避免在结构中实现Equals和GetHashcode - 因为编译器会使用按位内容+反射为参考成员自动实现Value类型。

看一下那篇文章: Which is best for data store Struct/Classes?

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

但大部分时间你都可以避免实现Equals和GetHashcode 您必须实现Equals和GetHashCode的情况适用于您不想考虑的字段。
例如,一个随时间变化的字段,如人的年龄或汽车的instantSpeed(如果你想在同一个地方的字典中找到它,对象的身份不应该改变)

问候,最好的代码

答案 4 :(得分:3)

两者之间的基本区别在于==运算符是静态的,即在编译时确定调用的适当方法,而在实例上以动态方式调用Equals方法。 /> 定义两者可能是最好的事情,即使在结构的情况下这个问题更少,因为结构不能被扩展(结构不能从另一个继承)。

答案 5 :(得分:0)

为了完整性,我还建议重载initialization方法:

zc.recipe.egg

这是一个真正的改进,因为Equals方法

的输入参数没有发生拳击

使用值类型的一些最佳做法:

  • 让它们永不变化
  • override Equals(以对象作为参数的那个);
  • overload等于获取相同值类型的另一个实例(例如* Equals(Complex other));
  • 重载运算符==和!=;
  • 覆盖GetHashCode

这来自这篇文章:http://theburningmonk.com/2015/07/beware-of-implicit-boxing-of-value-types/