簡體   English   中英

overload ==(和!=,當然)運算符,我可以繞過==來確定對象是否為空

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

當我嘗試在C#中重載operator ==和!=並按推薦重寫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)

當temp真的為null時,會發生一些異常。 並且我不能使用==來確定lhs是否為null,這將導致無限循環。

在這種情況下我該怎么辦

我能想到的一種方法是給我們一些像Class.Equal(對象,對象)(如果它存在的話)在我做檢查時繞過==。

解決問題的正常方法是什么?

謝謝。

您可以在等於覆蓋的頂部使用以下內容:

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

您應該考慮在運算符重載中使用靜態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主題 ,這是一個很好的樣本來源。

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

有一個更好的方法,然后使用運營商iscast

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

這是一個關於Equals運算符覆蓋和與null比較的快速測試:

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

調試不會進入操作員的身體:

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

我想你應該在==運算符實現中測試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);

因此,將為上面的所有==比較調用Object.Equals。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM