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 inDis called withbaseObject, it will return false, due to this part:Given that the value of
baseObjectis not a reference to an instance ofD,rightAsDshould benull, so it'll returnfalse.To demonstrate this, just change the types of the
baseObjectandderivedObjectvariables 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.