Why the resolution of the Equals method 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 am redirected to Object.Equals instead of Hello.Equals, although I specify the exact type in the generic argument?

+6
source share
2 answers

Because you did not tell the universal method that your object implements IEquatable<T> :

Try now:

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

In your ObjectsEqual method, you only have access to the TValue methods / properties / fields that are defined in the object class plus the methods that are defined in the interface / base class classes defined in the restrictions. No restrictions => you only have access to Equals(object) , GetHashCode() , GetType() , (and if you have a class restriction: operator== , operator!= .) Of these two virtual ( Equals(object) , GetHashCode() ), so you will use the "correct" version, the third will not usually be overwritten ( GetType() ), so you will probably use the "correct" version. Only two operators == / != Are often overwritten, and there you go! In your general method, you cannot use the β€œcorrect” version of these two !:-)

+11
source

Adding from MSDN :

Parameters of unlimited type.
Type parameters that have no restrictions, such as T in the public class SampleClass<T> { } , are called parameters of unlimited type.
Parameters of unlimited type have the following rules:

  • The != And == operators cannot be used because there is no guarantee that an argument of a particular type will support these operators.
  • They can be converted to and from System.Object or explicitly converted to any type of interface.
  • You can compare with null . If an unlimited parameter is compared to null , the comparison will always return false if the type argument is a value type.

In this case, TValue converted to the System.Object and Equals method.

+2
source

Source: https://habr.com/ru/post/953316/


All Articles