覆盖==运算符.如何比较null?

Fli*_*ter 132 .net c# null overloading operator-keyword

可能重复:
如何在没有无限递归的情况下检查'=='运算符重载中的空值?

对此可能有一个简单的答案......但它似乎在逃避我.这是一个简化的例子:

public class Person
{
   public string SocialSecurityNumber;
   public string FirstName;
   public string LastName;
}
Run Code Online (Sandbox Code Playgroud)

让我们说,对于这个特定的应用程序,如果社会安全号码匹配,并且两个名称都匹配,那么我们指的是同一个"人"是有效的.

public override bool Equals(object Obj)
{
    Person other = (Person)Obj;
    return (this.SocialSecurityNumber == other.SocialSecurityNumber &&
        this.FirstName == other.FirstName &&
        this.LastName == other.LastName);
}
Run Code Online (Sandbox Code Playgroud)

为了保持一致,我们还为团队中不使用该.Equals方法的开发人员覆盖==和!=运算符.

public static bool operator !=(Person person1, Person person2)
{
    return ! person1.Equals(person2);
}

public static bool operator ==(Person person1, Person person2)
{
    return person1.Equals(person2);
}
Run Code Online (Sandbox Code Playgroud)

好又花花公子,对吧?

但是,当Person对象发生时会发生什么null

你不能写:

if (person == null)
{
    //fail!
}
Run Code Online (Sandbox Code Playgroud)

因为这将导致运行==运算符覆盖,并且代码将在以下情况下失败:

person.Equals()
Run Code Online (Sandbox Code Playgroud)

方法调用,因为您无法在null实例上调用方法.

另一方面,您无法在== override中显式检查此条件,因为它会导致无限递归(以及Stack Overflow [dot com])

public static bool operator ==(Person person1, Person person2)
{
    if (person1 == null)
    {
         //any code here never gets executed!  We first die a slow painful death.
    }
    return person1.Equals(person2);
}
Run Code Online (Sandbox Code Playgroud)

那么,如何覆盖==和!=运算符以实现值相等并仍然考虑空对象?

我希望答案不是很简单.:-)

cdh*_*wie 241

使用object.ReferenceEquals(person1, null)而不是==运算符:

public static bool operator ==(Person person1, Person person2)
{
    if (object.ReferenceEquals(person1, null))
    {
         return object.ReferenceEquals(person2, null);
    }

    return person1.Equals(person2);
}
Run Code Online (Sandbox Code Playgroud)

  • @dtb:无论如何,JIT都会内联这个电话; 运行时性能将完全相同.请参阅http://stackoverflow.com/questions/735554/reference-equality-performance-difference-objectobj1-objectobj2-vs-obj (7认同)
  • VS 2017希望我现在使用<i> is </ i>运算符:left为null && right为null. (5认同)
  • `ReferenceEquals`虽然发出一个方法调用,但是转换为object会导致编译器只发出指令来比较引用的相等性.......但这可能算作邪恶的微观优化. (4认同)
  • 也许这是显而易见的,但您可能还想对`Person.Equals`覆盖中的`Obj`参数进行空检查.在我看来,做`person == null`仍然会导致调用`person.Equals(null)` (2认同)

Mik*_*ebb 17

我总是这样做(对于==和!=运算符)并且我为我创建的每个对象重用这个代码:

public static bool operator ==(Person lhs, Person rhs)
{
    // If left hand side is null...
    if (System.Object.ReferenceEquals(lhs, null))
    {
        // ...and right hand side is null...
        if (System.Object.ReferenceEquals(rhs, null))
        {
            //...both are null and are Equal.
            return true;
        }

        // ...right hand side is not null, therefore not Equal.
        return false;
    }

    // Return true if the fields match:
    return lhs.Equals(rhs);
}
Run Code Online (Sandbox Code Playgroud)

"!="然后是这样的:

public static bool operator !=(Person lhs, Person rhs)
{
    return !(lhs == rhs);
}
Run Code Online (Sandbox Code Playgroud)

编辑
我修改了==操作功能,以配合微软的建议的实施在这里.

  • 嗯,一方面,`rhs` 的 `null` 检查是多余的,因为 `Equals` 也必须执行它。余数可以表示为`return object.ReferenceEquals(lhs, rhs) || !object.ReferenceEquals(lhs, null) &amp;&amp; lhs.Equals(rhs);` - 显然,使用适当的格式(换行符、缩进)使其可读。如果这太晦涩难懂,请在注释中添加指向描述相等运算符语义要求的相应 MSDN 文章的链接。 (2认同)

rtp*_*tpg 11

你总是可以覆盖并放置

(Object)(person1)==null
Run Code Online (Sandbox Code Playgroud)

我想这会有用,但不确定.


小智 5

比任何这些方法都更简单的是只使用

public static bool operator ==(Person person1, Person person2)   
{   
    EqualityComparer<Person>.Default.Equals(person1, person2)
} 
Run Code Online (Sandbox Code Playgroud)

这与其他人提出的方法具有相同的空相等语义,但框架的问题是弄清楚细节:)


归档时间:

查看次数:

58755 次

最近记录:

7 年,6 月 前