Подтвердить что ты не робот

Overload == (и! =, конечно), могу ли я обходить ==, чтобы определить, является ли объект нулевым

когда я пытаюсь перегрузить 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 нулевым, что вызовет бесконечный цикл.

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

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

Каков нормальный способ решения проблемы?

Спасибо.

4b9b3361

Ответ 1

Вы должны использовать статический метод 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 Topic на MSDN, который является отличным источником образцов.

Ответ 2

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

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

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

EDIT:

Если 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);
} 

Ответ 3

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

Бедный человек 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);

Ответ 4

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

Ответ 5

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

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

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

Итак, Object.Equals будут вызываться для всех == сравнений выше.