Эффективные ошибки # 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