简体   繁体   中英

Extension method on Nullable<T> not called unless generic type is set explicitly

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.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM