Нуль == ноль? - PullRequest
       26

Нуль == ноль?

5 голосов
/ 02 ноября 2010

У меня есть объект типа Foo.
Foo имеет Id (int)

a) Является ли приведенный ниже код "хорошим"?
b) Что я должен вернутьесли оба имеют значение null?

// overload operator ==
public static bool operator ==(Foo a, Foo b)
{
    if (ReferenceEquals(x, y))
    {
        return true;
    }

    if (x == null && y == null)
    {
        return // ??? 
    }

    if (x == null || y == null)
    {
        return false; 
    }

    return x.Id == y.Id; // Ids are the same
}

public static bool Equals(Foo x, Foo y)
{
   return x == y;
}

EDIT:
c) Должен ли метод Equals вызвать оператор == или наоборот?

Последний вопрос
г) Возможно ли, что ReferenceEquals(x, y) == true И x.Id != y.Id?

Ответы [ 4 ]

14 голосов
/ 02 ноября 2010

Это фактически недоступный код, так как ReferenceEquals() является задокументированным для возврата true, если оба операнда равны нулю.

РЕДАКТИРОВАТЬ: Чтобы конкретно ответить на ваш вопрос (d): Когда ReferenceEquals возвращает true, то две ссылки должны быть одинаковыми; поэтому они указывают на один и тот же объект. Таким образом, если вы не делаете что-то непредсказуемое в методе доступа к свойству, значения для идентификатора будут считываться из одного и того же объекта и будут ожидаемыми такими же. (Мораль этой истории состоит в том, что свойства должны вести себя воспроизводимым образом без других побочных эффектов, например, возможно, присвоение идентификатора, если ни один из них уже не установлен)

Вполне возможно, что у вас может быть два объекта с одинаковым Id, но разными ссылками. Например:

Foo a = new Foo();
Foo b = new Foo();

ReferenceEquals() выдаст false при сравнении a и b (поскольку они различаются экземплярами ), но если этот конструктор не сделал ничего подобного для выделения Id, я бы ожидал их чтобы поделиться этим идентификатором и ваша проверка на равенство прошла бы.

9 голосов
/ 02 ноября 2010

Да

null - это не что иное, как внутренний указатель со значением ноль. Таким образом, он сравнивает две ссылки, имеющие значение ноль.

На самом деле object.ReferenceEquals(null, null) всегда верно из-за этого факта, поэтому вам не нужна вторая проверка.

if (ReferenceEquals(x, y))
{
    return true;
}

if (x == null && y == null) // THIS CHECK IS REDUNDANT!!!
{
    return true;
}

В последней точке == и Равные обрабатываются одинаково, если только для типов значений в штучной упаковке :

        object s1 = 2;
        object s2 =  1+1;

        Console.WriteLine(s1 == s2);
        Console.WriteLine(s1.Equals(s2));

Это производит false и true.

Точка d: NO это тот же объект, то же пространство памяти - если они указывают на поле на объекте.

4 голосов
/ 02 ноября 2010

да,

null == null

Я бы реорганизовал ваш код следующим образом

if(x!=null && y!=null)
   return x.id == y.id;
return x == null && y == null;
3 голосов
/ 02 ноября 2010

ReferenceEquals уже обрабатывает случай, когда оба аргумента равны нулю - MSDN заявляет «истина, если objA - это тот же экземпляр, что и objB, или если оба значения равны нулю; в противном случае - ложь».возобновляя его возвращаемое значение.

...