简体   繁体   English

overload ==(和!=,当然)运算符,我可以绕过==来确定对象是否为空

[英]overload == (and != , of course) operator, can I bypass == to determine whether the object is null

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. 当我尝试在C#中重载operator ==和!=并按推荐重写Equal时,我发现我无法区分普通对象和null。 For example, I defined a class Complex. 例如,我定义了一个类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. 当temp真的为null时,会发生一些异常。 And I can't use == to determine whether the lhs is null, which will cause infinite loop. 并且我不能使用==来确定lhs是否为null,这将导致无限循环。

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. 我能想到的一种方法是给我们一些像Class.Equal(对象,对象)(如果它存在的话)在我做检查时绕过==。

What is the normal way to solve the problem? 解决问题的正常方法是什么?

Thank you. 谢谢。

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. 您获得的异常可能是StackOverflowException,因为您的==运算符将导致无限递归。

EDIT: 编辑:

If Complex is a struct you should not have any problems with NullReferenceExceptions. 如果Complex是一个结构,那么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): 如果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 should consider using the static Equals method in the operator overloads (which will call the instance Equals method): 您应该考虑在运算符重载中使用静态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);
}

Note: You may also check for null in the Equals method. 注意:您也可以在Equals方法中检查null

You can also read the Object.Equals Topic on MSDN , which is a great source of samples. 您还可以在MSDN上阅读Object.Equals主题 ,这是一个很好的样本来源。

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);

There is a better approach then using operators is and cast : 有一个更好的方法,然后使用运营商iscast

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 : 这是一个关于Equals运算符覆盖和与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());

I think you shoud test for null in the == operator implementation. 我想你应该在==运算符实现中测试null。 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) 否则,当lhs为null时,你会调用Complex(null).Equals(我不知道C#,但在Java中这将是一个Nullpointer异常)

To test for null, I suggest something like: 要测试null,我建议像:

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. 因此,将为上面的所有==比较调用Object.Equals。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM