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?
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.)
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments