Unreachable code when overriding Object.Equals and implementing IEquatable<>?

I'm a litte bit confused right now. From my understanding the .NET runtime will pick the overloaded method that best suits the given parameter's type. So I would think, that in the snippet below the method Equals(object obj) will never be called with an instance of type Entry. Instead - because there exists the method Equals(Entry other) that has the correct parameter type - it will be called.

The documentation for IEquatable on MSDN states that

If you implement IEquatable, you should also override the base class implementations of Object.Equals(Object) and GetHashCode so that their behavior is consistent with that of the IEquatable.Equals method. If you do override Object.Equals(Object), your overridden implementation is also called in calls to the static Equals(System.Object, System.Object) method on your class.

My questions are:

  1. Is it correct, that the Equals(object obj) method below will never be called with an instance of type Entry?
  2. Wouldn't it then be enough to just return false in the Equals(object obj) method below?
  3. If so, why doesn't the compiler recognize the commented line below as unreachable?

The code I refer to:

sealed class Entry : IEquatable<Entry> {
    ...
    // Overrides Object.Equals
    public override bool Equals(object obj)
    {
        if (obj is Entry)
        {
            return this.Equals(obj as Entry); // Is this code reachable?
        }
        return false;
    }

    // Implements IEquatable<Entry>.Equals
    public bool Equals(Entry other)
    {
        return this.Hash.Equals(other.Hash)
            && this.Path.Equals(other.Path)
            && this.Order.Equals(other.Order);
    }

    public override int GetHashCode()
    {
        return base.GetHashCode();
    }
}

Thanks in advance for helping me!

Jon Skeet
people
quotationmark

Is it correct, that the Equals(object obj) method below will never be called with an instance of type Entry?

No. Consider:

object entry1 = new Entry(...);
object entry2 = new Entry(...);
bool equal = entry1.Equals(entry2);

The compile-time type of entry2 is object, not Entry, so this will still call Equals(object).

(Note that your GetHashCode implementation is decidedly dodgy, by the way - and you're currently not guarding against nulls anywhere. It doesn't help that we don't know whether Entry is a class or a struct.)

people

See more on this question at Stackoverflow