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

Adam Houldsworth

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?

Jon Skeet

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.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Extension Method with Generic Type

From Dev

The type 'MyObject' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable<T>'

From Dev

Need generic method to return type T unless T implements interface I, in which case return I

From Dev

Generic type vs Extension method

From Dev

Extension method for nested generic type

From Dev

Generic type vs Extension method

From Dev

Generic method to return Nullable Type values

From Dev

Nullable nested type in extension method in C#

From Dev

Can't omit the extension type argument when calling generic extension method with mutually constrained type parameters

From Dev

Method with Generic Type, set value

From Dev

Method with Generic Type, set value

From Dev

Call a generic method and set the generic type at runtime

From Dev

Is there a way to get the Generic Type from an Extension method?

From Dev

Generic extension method can return type of IEnumerable?

From Dev

Method with generic type parameter inside Swift extension

From Dev

Is it possible to write an extension method for a generic Enum type?

From Dev

How to work with Generic type members in extension method?

From Dev

Generic type nullable and ToString

From Dev

Nested Func<T, object> in a Generic Extension Method

From Dev

Extension method with generic parameter called from subclass instance

From Dev

Is it possible to define a "not Nullable<T>" constraint in a C# generic method?

From Dev

Dapper won't read object properties unless explicitly listed as anonymous type

From Dev

Dapper won't read object properties unless explicitly listed as anonymous type

From Dev

one generic class create generic extension with expression<T,bool> method

From Dev

Firestore set() method does not insert document into collection unless get() method of ApiFuture<WriteResult> is called

From Dev

Set no type for a static method in a generic class

From Dev

Set only second argument type in generic method

From Dev

Can I create a generic method that takes a value type or a reference type but always returns a nullable type

From Dev

The type 'T' cannot be used as type parameter 'T' in the generic type or method

Related Related

  1. 1

    Extension Method with Generic Type

  2. 2

    The type 'MyObject' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable<T>'

  3. 3

    Need generic method to return type T unless T implements interface I, in which case return I

  4. 4

    Generic type vs Extension method

  5. 5

    Extension method for nested generic type

  6. 6

    Generic type vs Extension method

  7. 7

    Generic method to return Nullable Type values

  8. 8

    Nullable nested type in extension method in C#

  9. 9

    Can't omit the extension type argument when calling generic extension method with mutually constrained type parameters

  10. 10

    Method with Generic Type, set value

  11. 11

    Method with Generic Type, set value

  12. 12

    Call a generic method and set the generic type at runtime

  13. 13

    Is there a way to get the Generic Type from an Extension method?

  14. 14

    Generic extension method can return type of IEnumerable?

  15. 15

    Method with generic type parameter inside Swift extension

  16. 16

    Is it possible to write an extension method for a generic Enum type?

  17. 17

    How to work with Generic type members in extension method?

  18. 18

    Generic type nullable and ToString

  19. 19

    Nested Func<T, object> in a Generic Extension Method

  20. 20

    Extension method with generic parameter called from subclass instance

  21. 21

    Is it possible to define a "not Nullable<T>" constraint in a C# generic method?

  22. 22

    Dapper won't read object properties unless explicitly listed as anonymous type

  23. 23

    Dapper won't read object properties unless explicitly listed as anonymous type

  24. 24

    one generic class create generic extension with expression<T,bool> method

  25. 25

    Firestore set() method does not insert document into collection unless get() method of ApiFuture<WriteResult> is called

  26. 26

    Set no type for a static method in a generic class

  27. 27

    Set only second argument type in generic method

  28. 28

    Can I create a generic method that takes a value type or a reference type but always returns a nullable type

  29. 29

    The type 'T' cannot be used as type parameter 'T' in the generic type or method

HotTag

Archive