重写 == 运算符。如何与 null 进行比较?
可能有一个简单的答案......但它似乎在逃避我。这是一个简化的示例:
public class Person
{
public string SocialSecurityNumber;
public string FirstName;
public string LastName;
}
假设对于这个特定的应用程序,如果社会安全号码匹配并且两个名字匹配,那么我们指的是同一个“人”。
public override bool Equals(object Obj)
{
Person other = (Person)Obj;
return (this.SocialSecurityNumber == other.SocialSecurityNumber &&
this.FirstName == other.FirstName &&
this.LastName == other.LastName);
}
为了保持一致,我们还为团队中不使用 .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);
}
很好,花花公子,对吧?
但是,当 Person 对象为 null
时会发生什么?
您不能编写:
if (person == null)
{
//fail!
}
因为这将导致 == 运算符重写运行,并且代码将在 :
person.Equals()
方法调用上失败,因为您无法在 null 实例上调用方法。
另一方面,您无法在 == 覆盖中显式检查此条件,因为它会导致无限递归(以及堆栈溢出 [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);
}
那么,如何覆盖 == 和 != 运算符为了值相等并且仍然考虑空对象?
我希望答案不会简单得令人痛苦。 :-)
Possible Duplicate:
How do I check for nulls in an ‘==’ operator overload without infinite recursion?
There is probably an easy answer to this...but it seems to be eluding me. Here is a simplified example:
public class Person
{
public string SocialSecurityNumber;
public string FirstName;
public string LastName;
}
Let's say that for this particular application, it is valid to say that if the social security numbers match, and both names match, then we are referring to the same "person".
public override bool Equals(object Obj)
{
Person other = (Person)Obj;
return (this.SocialSecurityNumber == other.SocialSecurityNumber &&
this.FirstName == other.FirstName &&
this.LastName == other.LastName);
}
To keep things consistent, we override the == and != operators, too, for the developers on the team who don't use the .Equals
method.
public static bool operator !=(Person person1, Person person2)
{
return ! person1.Equals(person2);
}
public static bool operator ==(Person person1, Person person2)
{
return person1.Equals(person2);
}
Fine and dandy, right?
However, what happens when a Person object is null
?
You can't write:
if (person == null)
{
//fail!
}
Since this will cause the == operator override to run, and the code will fail on the:
person.Equals()
method call, since you can't call a method on a null instance.
On the other hand, you can't explicitly check for this condition inside the == override, since it would cause an infinite recursion (and a 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);
}
So, how do you override the == and != operators for value equality and still account for null objects?
I hope that the answer is not painfully simple. :-)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
使用
object.ReferenceEquals(person1, null)
或新的 is 运算符 而不是==
运算符:Use
object.ReferenceEquals(person1, null)
or the new is operator instead of the==
operator:我总是这样做(对于 == 和 != 运算符),并且我为创建的每个对象重用此代码:
“!=”然后像这样:
编辑
我修改了
==
运算符函数以匹配 Microsoft 建议的实现 在这里。I've always done it this way (for the == and != operators) and I reuse this code for every object I create:
"!=" then goes like this:
Edit
I modified the
==
operator function to match Microsoft's suggested implementation here.你总是可以覆盖并把
我想象这会起作用,但不确定。
you could alway override and put
I'd imagine this would work, not sure though.
比这些方法中的任何一种都更容易使用
,这与其他人提出的方法具有相同的空相等语义,但找出细节是框架的问题:)
Easier than any of those approaches would be to just use
This has the same null equality semantics as the approaches that everyone else is proposing, but it's the framework's problem to figure out the details :)
最终(假设)例程如下。它与@cdhowie 的第一个接受的响应非常相似。
感谢您的精彩回复!
//* -
.Equals()
对 person2 执行 null 检查The final (hypothetical) routine is below. It is very similar to @cdhowie's first accepted response.
Thanks for the great responses!
//* -
.Equals()
performs the null check on person2将
Person
实例转换为object
:Cast the
Person
instance toobject
:将 Person 转换为 Object,然后执行比较:
Cast the Person to an Object and then perform the comparison:
cdhowie 通过使用
ReferenceEquals
实现了盈利,但值得注意的是,如果有人直接将null
传递给Equals
,您仍然可能会遇到异常。另外,如果您要覆盖Equals
,那么几乎总是值得实现IEquatable
所以我会这样做。当然,您永远不应该覆盖
Equals
也不应该覆盖GetHashCode()
还值得注意的是,身份意味着平等(也就是说,对于任何有效的“平等”概念)总是等于它本身)。由于相等测试可能很昂贵并且发生在循环中,并且由于在实际代码中将某些东西与自身进行比较往往很常见(特别是如果对象在多个地方传递),因此值得添加作为快捷方式:
Just how much
ReferenceEquals(this, other)
的好处捷径可能会根据类的性质而有很大差异,但是否值得这样做是人们应该始终考虑的事情,所以我包括这里的技术。cdhowie is on the money with the use of
ReferenceEquals
, but it's worth noting that you can still get an exception if someone passesnull
directly toEquals
. Also, if you are going to overrideEquals
it's almost always worth implementingIEquatable<T>
so I would instead have.And of course, you should never override
Equals
and not overrideGetHashCode()
It's also worth noting that identity entails equality (that is, for any valid concept of "equality" something is always equal to itself). Since equality tests can be expensive and occur in loops, and since comparing something with itself tends to be quite common in real code (esp. if objects are passed around in several places), it can be worth adding as a shortcut:
Just how much of a benefit short-cutting on
ReferenceEquals(this, other)
is can vary considerably depending on the nature of the class, but whether it is worth while doing or not is something one should always consider, so I include the technique here.持续重载这些运算符非常困难。 我对相关问题可以作为模板。
基本上,您首先需要进行引用 (
object.ReferenceEquals
) 测试以查看对象是否为null
。 然后你调用Equals
。Overloading these operators consistently is pretty hard. My answer to a related question may serve as a template.
Basically, you first need to do a reference (
object.ReferenceEquals
) test to see if the object isnull
. Then you callEquals
.