重载 == (当然还有 != )运算符,我可以绕过 == 来确定对象是否为 null

发布于 2024-09-05 02:59:17 字数 808 浏览 3 评论 0原文

当我尝试在 C# 中重载运算符 == 和 != 并按照建议覆盖 Equal 时,我发现无法区分普通对象和 null。例如,我定义了一个类Complex。

public static bool operator ==(Complex lhs, Complex rhs)
{
    return lhs.Equals(rhs);
}

public static bool operator !=(Complex lhs, Complex rhs)
{
    return !lhs.Equals(rhs);
}

public override bool Equals(object obj)
{
    if (obj is Complex)
    {
        return (((Complex)obj).Real == this.Real &&
                   ((Complex)obj).Imaginary == this.Imaginary);
    }
    else
    {
        return false;
    }
}

但是当我想使用

if (temp == null)

When temp is true null 时,会发生一些异常。而且我无法使用==来判断lhs是否为null,这会导致无限循环。

这种情况我该怎么办。

我能想到的一种方法是,当我进行检查时,我们可以使用诸如 Class.Equal(object, object) (如果存在)之类的东西来绕过 == 。

解决问题的正常方法是什么?

谢谢。

when I try to overload operator == and != in C#, and override Equal as recommended, I found I have no way to distinguish a normal object and null. For example, I defined a class Complex.

public static bool operator ==(Complex lhs, Complex rhs)
{
    return lhs.Equals(rhs);
}

public static bool operator !=(Complex lhs, Complex rhs)
{
    return !lhs.Equals(rhs);
}

public override bool Equals(object obj)
{
    if (obj is Complex)
    {
        return (((Complex)obj).Real == this.Real &&
                   ((Complex)obj).Imaginary == this.Imaginary);
    }
    else
    {
        return false;
    }
}

But when I want to use

if (temp == null)

When temp is really null, some exception happens. And I can't use == to determine whether the lhs is null, which will cause infinite loop.

What should I do in this situation.

One way I can think of is to us some thing like Class.Equal(object, object) (if it exists) to bypass the == when I do the check.

What is the normal way to solve the problem?

Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

祁梦 2024-09-12 02:59:17

您可以在 Equals 覆盖的顶部使用以下内容:

if (Object.ReferenceEquals(obj, null))
    return false;

您收到的异常可能是 StackOverflowException,因为您的 == 运算符将导致无限递归。

编辑:

如果 Complex 是一个结构体,那么 NullReferenceExceptions 就不会有任何问题。如果 Complex 是一个类,您可以更改 == 和 != 运算符重载的实现以避免异常(Laurent Etiemble 已经在他的回答中指出了这一点):

public static bool operator ==(Complex lhs, Complex rhs)
{
    return Equals(lhs, rhs);
}

public static bool operator !=(Complex lhs, Complex rhs)
{
    return !Equals(lhs, rhs);
} 

You can use the following at the top of your Equals override:

if (Object.ReferenceEquals(obj, null))
    return false;

The exception you are getting is probably a StackOverflowException because your == operator will cause infinite recursion.

EDIT:

If Complex is a struct you should not have any problems with NullReferenceExceptions. If Complex is a class you can change your implementation of the == and != operator overloads to avoid the exception (Laurent Etiemble already pointed this out in his answer):

public static bool operator ==(Complex lhs, Complex rhs)
{
    return Equals(lhs, rhs);
}

public static bool operator !=(Complex lhs, Complex rhs)
{
    return !Equals(lhs, rhs);
} 
ゞ记忆︶ㄣ 2024-09-12 02:59:17

您应该考虑在运算符重载中使用静态 Equals 方法(这将调用实例 Equals 方法):

public static bool operator ==(Complex lhs, Complex rhs)
{
    return Equals(lhs, rhs);
}

public static bool operator !=(Complex lhs, Complex rhs)
{
    return !Equals(lhs, rhs);
}

注意:您还可以在 Equals 方法中检查 null

您还可以阅读 MSDN 上的 Object.Equals 主题< /a>,这是一个很好的样本来源。

You should consider using the static Equals method in the operator overloads (which will call the instance Equals method):

public static bool operator ==(Complex lhs, Complex rhs)
{
    return Equals(lhs, rhs);
}

public static bool operator !=(Complex lhs, Complex rhs)
{
    return !Equals(lhs, rhs);
}

Note: You may also check for null in the Equals method.

You can also read the Object.Equals Topic on MSDN, which is a great source of samples.

七婞 2024-09-12 02:59:17
public static bool operator ==(Complex lhs, Complex rhs)
{
    if (Object.ReferenceEquals(lhs, null))
    {
        return Object.ReferenceEquals(rhs, null);
    }

    return lhs.Equals(rhs);
}

public static bool operator !=(Complex lhs, Complex rhs)
{
    return !(lhs == rhs);
}

穷人的单元测试

Action<Complex, Complex> tester = (left, right) =>
{
    Console.WriteLine(left == right);
    Console.WriteLine(left != right);
    Console.WriteLine(left == null);
    Console.WriteLine(left != null);
    Console.WriteLine("---");
};

tester(new Complex(), new Complex());
tester(null, new Complex());
tester(null, null);
tester(new Complex(), null);
public static bool operator ==(Complex lhs, Complex rhs)
{
    if (Object.ReferenceEquals(lhs, null))
    {
        return Object.ReferenceEquals(rhs, null);
    }

    return lhs.Equals(rhs);
}

public static bool operator !=(Complex lhs, Complex rhs)
{
    return !(lhs == rhs);
}

Poor man's unit test

Action<Complex, Complex> tester = (left, right) =>
{
    Console.WriteLine(left == right);
    Console.WriteLine(left != right);
    Console.WriteLine(left == null);
    Console.WriteLine(left != null);
    Console.WriteLine("---");
};

tester(new Complex(), new Complex());
tester(null, new Complex());
tester(null, null);
tester(new Complex(), null);
绝不服输 2024-09-12 02:59:17

我认为你应该在 == 运算符实现中测试 null 。否则,当 lhs 为 null 时,您将调用 Complex(null).Equals (我不知道 C# 中的情况,但在 Java 中这将是一个 Nullpointer 异常)

要测试 null,我建议类似:

if (null == lhs && null == rhs) return true
else if (null == lhs) return false
else return lhs.Equals(rhs);

So Object.Equals上面所有的 == 比较都会被调用。

I think you shoud test for null in the == operator implementation. Otherwise, when lhs is null, you'd call Complex(null).Equals (I don't know for C#, but in Java this would be a Nullpointer Exception)

To test for null, I suggest something like:

if (null == lhs && null == rhs) return true
else if (null == lhs) return false
else return lhs.Equals(rhs);

So Object.Equals will be called for all == comparisons above.

与君绝 2024-09-12 02:59:17

有一个更好的方法,然后使用运算符 iscast

Complex c = obj as Complex;
return (c != null) && (c.Real == this.Real) && (c.Imaginary == this.Imaginary);

以下是关于 Equals 运算符覆盖并与 null< 进行比较的快速测试/code>:

class Complex
{
    public override bool Equals(object obj)
    {
        if (obj is Complex)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}

调试不会进入操作员的主体:

var b = (new Complex() == new Complex());

There is a better approach then using operators is and cast:

Complex c = obj as Complex;
return (c != null) && (c.Real == this.Real) && (c.Imaginary == this.Imaginary);

Here is a quick test concerning Equals operator override and comparing with null:

class Complex
{
    public override bool Equals(object obj)
    {
        if (obj is Complex)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}

Debugging doesn't step into operator's body:

var b = (new Complex() == new Complex());
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文