Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.2k views
in Technique[技术] by (71.8m points)

c# - Why "Equals" method resolution with generics differs from explicit calls

I have the following example:

namespace ComparisonExample
{
    class Program
    {
        static void Main(string[] args)
        {
            var hello1 = new Hello();
            var hello2 = new Hello();

            // calls Hello.Equals
            var compareExplicitly = hello1.Equals(hello2);

            // calls Object.Equals
            var compareWithGenerics = ObjectsEqual<Hello>(hello1, hello2); 
        }

        private static bool ObjectsEqual<TValue>(TValue value1, TValue value2)
        {
            return value1.Equals(value2);
        }
    }

    class Hello : IEquatable<Hello>
    {
        public bool Equals(Hello other)
        {
            return true; // doesn't matter
        }
    }
}

The question is why in the second "Equals" call I'm redirected to Object.Equals instead of Hello.Equals even though I'm specifying the exact type in generic argument?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Because you haven't told the generic method that your object implements IEquatable<T>:

Try now with:

private static bool ObjectsEqual<TValue>(TValue value1, TValue value2) 
               where TValue : IEquatable<TValue> // IMPORTANT!!!
{
    return value1.Equals(value2);
}

In your ObjectsEqual method you have access only to methods/properties/fields of TValue that are defined in the object class plus the methods that are defined in the interfaces/base classes defined in the constraints. No constraints => you have access only to Equals(object), GetHashCode(), GetType(), (and if you have the constraint class: operator==, operator!=.) Of these two are virtual (Equals(object), GetHashCode()), so you'll use the "correct" version, the third isn't normally overwritten (GetType()), so you'll probably use the "correct" version. Only the two operators ==/!= are often overwritten and lo and behold! In your generic method you can't use the "correct" version of the two! :-)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...