7

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

当我为对象重载 == 运算符时,我通常会编写如下内容:

    public static bool operator ==(MyObject uq1, MyObject uq2) {
        if (((object)uq1 == null) || ((object)uq2 == null)) return false;
        return uq1.Field1 == uq2.Field1 && uq1.Field2 == uq2.Field2;
    }

如果您不向下转换为对象,则该函数会递归到自身,但我想知道是否没有更好的方法?

4

7 回答 7

7

正如微软所说,

运算符 == 重载的一个常见错误是使用 (a == b)、(a == null) 或 (b == null) 来检查引用是否相等。相反,这会导致调用重载运算符 ==,从而导致无限循环。使用 ReferenceEquals 或将类型转换为 Object,以避免循环。

所以使用 ReferenceEquals(a, null) || ReferenceEquals(b, null) 是一种可能性,但转换为对象同样好(我相信实际上是等价的)。

所以是的,似乎应该有更好的方法,但您使用的方法是推荐的方法。

然而,正如已经指出的那样,当覆盖 == 时,你真的应该覆盖 Equals。由于 LINQ 提供程序是用不同的语言编写并在运行时进行表达式解析,即使您自己拥有所有代码,谁知道什么时候您会因为不这样做而感到厌烦。

于 2008-09-17T20:05:03.953 回答
2

@neouser99:这是正确的解决方案,但是缺少的部分是在覆盖相等运算符(运算符 ==)时,您还应该覆盖 Equals 函数并简单地让运算符调用该函数。并非所有 .NET 语言都支持运算符重载,因此是重写 Equals 函数的原因。

于 2008-09-17T20:03:25.330 回答
2

ReferenceEquals(object obj1, object obj2)

于 2008-09-17T19:55:40.077 回答
0

只需使用 Resharper 为您创建 Equals 和 GetHashCode 方法。它为此目的创建了最全面的代码。

更新 我不是故意发布的——我更喜欢人们使用 Resharper 的功能而不是复制粘贴,因为代码从一个类到另一个类会发生变化。至于在没有 Resharper 的情况下开发 C# - 我不明白你是怎么生活的,伙计。

无论如何,这是一个简单类的代码(由旧版本 Resharper 3.0 生成 - 我有 4.0 在工作,我目前不记得它是否创建相同的代码)

public class Foo : IEquatable<Foo>
{
    public static bool operator !=(Foo foo1, Foo foo2)
    {
        return !Equals(foo1, foo2);
    }

    public static bool operator ==(Foo foo1, Foo foo2)
    {
        return Equals(foo1, foo2);
    }

    public bool Equals(Foo foo)
    {
        if (foo == null) return false;
        return y == foo.y && x == foo.x;
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(this, obj)) return true;
        return Equals(obj as Foo);
    }

    public override int GetHashCode()
    {
        return y + 29*x;
    }

    private int y;
    private int x;
}
于 2008-09-17T20:38:28.383 回答
-1

遵循 DB 处理:

null == <anything> is always false
于 2008-09-17T20:00:13.560 回答
-1

但是你为什么不创建一个对象成员函数呢?它当然不能在 Null 引用上调用,因此您确定第一个参数不是 Null。

事实上,你失去了二元运算符的对称性,但仍然......

(注意 Purfideas 的回答:如果需要,Null 可能等于 Null 作为数组的哨兵值)

还要考虑 == 函数的语义:有时您真的希望能够选择是否测试

  • 身份(指向同一个对象)
  • 价值平等
  • 等价(例如 1.000001 等价于 .9999999 )
于 2008-09-17T20:06:07.383 回答
-1
if ((object)uq1 == null) 
    return ((object)uq2 == null)
else if ((object)uq2 == null)
    return false;
else
    //return normal comparison

This compares them as equal when both are null.

于 2008-09-17T19:58:20.333 回答