重载的操作符参数始终为空

问题描述:

所以我有一个类重写Equals(object obj)和GetHashCode()以及实现IEquatable。为了使这种类型的工作在检查平等时更自然一些,我认为,嘿,我会超负荷平等运算符和不平等运算符,无后顾之忧......重载的操作符参数始终为空

呃哦,忧虑...考虑以下 - 其中两个实例的myType不为空:

if (myType != container.myType) //NullReferenceException 
{ 
    //never get here 
} 
//never get here either 

现在,容器是另一个类以保存其中用于缓存项以外的东西的的myType一个实例。

下面是对的myType实际的(相关)代码:

public class MyType : IEquatable<MyType> 
{ 
    public static bool operator ==(MyType myTypeA, MyType myTypeB) 
    { 
     return myTypeA.Equals(myTypeB); 
    } 

    public static bool operator !=(MyType myTypeA, MyType myTypeB) 
    { 
     return !(myTypeA == myTypeB); 
    } 

    public override bool Equals(object obj) 
    { 
     if (obj != null && obj is MyType) 
     { 
      return Equals((MyType)obj); 
     } 
     return false; 
    } 

    public bool Equals(MyType other) 
    { 
     if (other != null) 
     { 
      return other.ToString() == ToString(); 
     } 
     return false; 
    } 
} 

在这方面的经验吗?

谢谢。

+0

你能后的堆栈跟踪?因为如果你得到一个NRE,东西必须是空的。你是如何验证这两个参数都不为空的? – 2010-10-03 15:10:50

棘手的......问题是,你使用等号平等覆盖内部如下:

public bool Equals(MyType other) 
{ 
    if (other != null) 

它去你重载=操作符,这反过来去你的==操作符! ,它试图做null.Equals ...

+0

这是一个常见的错误。或者使用'object.ReferenceEquals'或者'if((object)other!=(object)null){...}'将操作数(或者其中的一个)这是静态的(因此从未被覆盖)。 – 2013-07-24 08:24:33

两个指针 -

  1. 如果您已经撤消了对类==!=,确保使用ReferenceEquals检查在过载实现中为null,而不是==,因为这会调用您的重载操作符并进入循环或试图在空this引用上调用Equals,这可能是在这里发生的事情。
  2. 请勿覆盖类别上的==!=。这些运营商是为价值平等而设计的,而类别的设计并非真正具有价值平等。要么删除操作员重载,要么使结构成为一个结构。
+0

谢谢,这样,并且在不遗漏调用的情况下逐步执行代码时的一点耐心,让我意识到Equals实际上被调用为null作为导致使用null调用相等运算符的比较,导致另一个等于null的呼叫,这导致另一个带有两个空值的平等运算符呼叫,以及BANG。可能会更糟糕,可能会有一个可怕的循环。 – 2010-10-03 16:30:58

正如其他人已经声明,你需要仔细检查空值,因为它会再次调用你的相等函数,通常导致*Exception。

当我使用IEquatable接口类我通常使用下面的代码:

public override bool Equals(object obj) 
{ 
    // If obj isn't MyType then 'as' will pass in null 
    return this.Equals(obj as MyType); 
} 

public bool Equals(MyType other) 
{ 
    if (object.ReferenceEquals(other, null)) 
    { 
     return false; 
    } 

    // Actual comparison code here 
    return other.ToString() == this.ToString(); 
}