I am making the move from java to c#. I am reading Bill Wagner's book, Effective C# second edition. I am currently at item 6 "Understand the relationships among the many different concepts of equality" in chapter 1 where there's a sample code in pages 40-41-42 that is supposed to show how incorrectly implementing Equals can lead to errors, errors that i am unable to reproduce, it looks like an error in the sample. here's the code below
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
}
and class D inheriting from 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
}
according to the book, the following code
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");
"the second comparison will never return true", well it does. I mean since D is a subclass of B, the second comparison will end up calling the Equals method from B which returns true and that makes total sense to me. am i missing something?
I suspect Bill meant that if the overridden
Equals(object)
method inD
is called withbaseObject
, it will return false, due to this part:Given that the value of
baseObject
is not a reference to an instance ofD
,rightAsD
should benull
, so it'll returnfalse
.To demonstrate this, just change the types of the
baseObject
andderivedObject
variables toobject
. (Don't change the values they're initialized to, just the declared type.) Alternatively, just cast toobject
:So the book is right in saying that the implementation has a problem - it's just that the sample doesn't quite demonstrate it.