Reputation: 64517
While investigating another question: "Why there is no Nullable<T>.Equals(T value) method?" I made an extension method on Nullable<T>
that exposed a generic Equals<T>(T)
method:
public static class NullableExtensions
{
public static bool Equals<T>(this T? left, T right) where T : struct, IEquatable<T>
{
if (!left.HasValue)
return false;
return right.Equals(left.Value);
}
}
However, calling it like so:
double? d = null;
d.Equals(0.0);
Calls into the base Equals(object)
with boxing, as you can see in the IL:
IL_0000: nop
IL_0001: ldloca.s d
IL_0003: initobj valuetype [mscorlib]System.Nullable`1<float64>
IL_0009: ldloca.s d
IL_000b: ldc.r8 0.0
IL_0014: box [mscorlib]System.Double
IL_0019: constrained. valuetype [mscorlib]System.Nullable`1<float64>
IL_001f: callvirt instance bool [mscorlib]System.Object::Equals(object)
If I change the call to explicitly state the generic type:
d.Equals<double>(0.0);
It calls my extension method:
IL_0000: nop
IL_0001: ldloca.s d
IL_0003: initobj valuetype [mscorlib]System.Nullable`1<float64>
IL_0009: ldloc.0
IL_000a: ldc.r8 0.0
IL_0013: call bool ConsoleApplication8.NullableExtensions::Equals<float64>(valuetype [mscorlib]System.Nullable`1<!!0>, !!0)
Why does the compiler not choose the extension method over the Equals(object)
method?
Is it because I've just chosen a poor method name of Equals<T>(T)
where it isn't actually a true override of Equals
and not part of the inheritance look-up?
Upvotes: 3
Views: 795
Reputation: 1503140
Why does the compiler not choose the extension method over the Equals(object) method?
Extension methods are only considered if there are no other alternatives. It's a fall-back - it's not part of normal overload resolution for instance methods. This isn't specific to nullable types - it's part of normal extension method invocation.
From section 7.6.5.2 of the spec:
In a method invocation of one of the forms
[...]
if the normal processing of the invocation finds no applicable methods, an attempt is made to process the construct as an extension method invocation.
(Emphasis mine.)
Upvotes: 9