оператор overload == (и! =, конечно), можно ли обойти ==, чтобы определить, является ли объект нулевым - PullRequest
17 голосов
/ 09 июня 2010

Когда я пытаюсь перегрузить операторы == и! = В C # и переопределить значение Equal, как рекомендовано, я обнаружил, что у меня нет способа различить обычный объект и ноль. Например, я определил класс 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 действительно равен нулю, происходит какое-то исключение. И я не могу использовать ==, чтобы определить, является ли lhs нулевым, что приведет к бесконечному циклу.

Что мне делать в этой ситуации.

Один из способов, который я могу придумать, - это что-то вроде Class.Equal (объект, объект) (если он существует), чтобы обойти ==, когда я делаю проверку.

Как обычно решить проблему?

Спасибо.

Ответы [ 5 ]

14 голосов
/ 09 июня 2010

Вы можете использовать следующее в верхней части переопределения Equals:

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

Исключением, которое вы получаете, вероятно, является StackOverflowException, поскольку ваш оператор == вызовет бесконечную рекурсию.

EDIT:

Если Complex является структурой, у вас не должно быть проблем с NullReferenceExceptions. Если Complex - это класс, вы можете изменить свою реализацию перегрузок операторов == и! =, Чтобы избежать исключения (Лоран Этьембл уже указал это в своем ответе):

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

public static bool operator !=(Complex lhs, Complex rhs)
{
    return !Equals(lhs, rhs);
} 
12 голосов
/ 09 июня 2010

Вам следует рассмотреть использование статического метода 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);
}

Примечание: Вы также можете проверить null в методе Equals.

Вы также можете прочитать тему Object.Equals на MSDN , которая является отличным источником примеров.

2 голосов
/ 09 июня 2010
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);
0 голосов
/ 09 июня 2010

Я думаю, что вы должны проверить на null в реализации оператора ==.В противном случае, когда lhs имеет значение null, вы бы вызвали Complex (null) .Equals (я не знаю для C #, но в Java это будет исключение Nullpointer)

Чтобы проверить на нулевое значение, я предлагаюнапример:

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

Поэтому Object.Equals будет вызываться для всех сравнений == выше.

0 голосов
/ 09 июня 2010

Есть лучший подход, чем использование операторов is и cast:

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());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...