effective c# second edition errata

236 Views Asked by At

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?

2

There are 2 best solutions below

1
On BEST ANSWER

I suspect Bill meant that if the overridden Equals(object) method in D is called with baseObject, it will return false, due to this part:

D rightAsD = right as D;

if (rightAsD == null)
    return false;

Given that the value of baseObject is not a reference to an instance of D, rightAsD should be null, so it'll return false.

To demonstrate this, just change the types of the baseObject and derivedObject variables to object. (Don't change the values they're initialized to, just the declared type.) Alternatively, just cast to object:

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

So the book is right in saying that the implementation has a problem - it's just that the sample doesn't quite demonstrate it.

4
On

This is due to the as operator and inheritance.

Suppose you have 2 classes, A and B, and B derives from 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