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?
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! :-)
Addition from MSDN:
Unbounded Type Parameters.
Type parameters that have no constraints, such as T
in public class SampleClass<T> { }
, are called unbounded type parameters.
Unbounded type parameters have the following rules:
!=
and ==
operators cannot be used because there is no guarantee that the concrete type argument will support these operators.System.Object
or explicitly converted to any interface type.null
. If an unbounded parameter is compared to null
, the comparison will always return false
if the type argument is a value type.In this case TValue
is converted to System.Object
and Equals
method called.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With