Эффективные ошибки # c издание второго

Я делаю переход с Java на C#. Я читаю книгу Билла Вагнера, второе издание Effective C#. Я в настоящее время нахожусь в пункте 6 "Поймите отношения между многими различными понятиями равенства" в главе 1, где есть пример кода на страницах 40-41-42, который должен показать, как неправильно реализация Equals может привести к ошибкам, ошибкам, которые я не могу воспроизвести, это похоже на ошибку в образце. вот код ниже

public class B : IEquatable<D>
{
    public override bool Equals(object right)
    {
        //
        if (object.ReferenceEquals(right, null))
            return false;
        // Check reference equality:
        if (object.ReferenceEquals(this, right))
            return true;
        // Problems here, discussed below.
        B rightAsB = right as B;
        if (rightAsB == null)
            return false;
        return this.Equals(rightAsB);
    }

    #region IEquatable<B> Members
    public bool Equals(B other)
    {
        // elided
        return true;
    }
    #endregion
}

и класс D, наследующий от B

public class D : B,IEquatable<D>
{
    // etc.
    public override bool Equals(object right)
    {
        // check null:
        if (object.ReferenceEquals(right, null))
            return false;
        if (object.ReferenceEquals(this, right))
            return true;
        // Problems here.
        D rightAsD = right as D;

        if (rightAsD == null)
            return false;
        if (base.Equals(rightAsD) == false)
            return false;
        return this.Equals(rightAsD);
    }

    #region IEquatable<D> Members
    public bool Equals(D other)
    {
        // elided.
        return true; // or false, based on test
    }
    #endregion
}

согласно книге, следующий код

        B baseObject = new B();
        D derivedObject = new D();
        // Comparison 1.
        if (baseObject.Equals(derivedObject))
            Console.WriteLine("Equals");
        else
            Console.WriteLine("Not Equal");
        // Comparison 2.
        if (derivedObject.Equals(baseObject))
            Console.WriteLine("Equals");
        else
            Console.WriteLine("Not Equal");

"второе сравнение никогда не вернет истину", что ж, это так. Я имею в виду, так как D является подклассом B, второе сравнение в конечном итоге вызовет метод Equals из B, который возвращает true, и это имеет для меня смысл. я что-то пропустил?

2 ответа

Решение

Я подозреваю, что Билл имел в виду, что если переопределено Equals(object) метод в D называется с baseObject, он вернет false, из-за этой части:

D rightAsD = right as D;

if (rightAsD == null)
    return false;

Учитывая, что значение baseObject не является ссылкой на экземпляр D, rightAsD должно быть nullтак что вернусь false,

Чтобы продемонстрировать это, просто измените типы baseObject а также derivedObject переменные к object, (Не изменяйте значения, для которых они инициализированы, только объявленный тип.) В качестве альтернативы, просто приведите к object:

if (derivedObject.Equals((object) baseObject))

Так что в книге правильно сказать, что у реализации есть проблема - просто пример не совсем демонстрирует это.

Это связано с as оператор и наследование.

Предположим, у вас есть 2 класса, A а также B, а также B происходит от A,

A a = new A();
B b = new B();

A x = b as A; // x is b
B y = a as B; // y is null
Другие вопросы по тегам