T>在可空&LT扩展方法;不叫除非泛型类型设置明确 [英] Extension method on Nullable<T> not called unless generic type is set explicitly

查看:237
本文介绍了T>在可空&LT扩展方法;不叫除非泛型类型设置明确的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在调查另外一个问题:为什么有无可空< T> .Equals(T值)方法我所做的扩展方法可空< T> 暴露一个通用的等于< T>(T)方法:

 公共静态类NullableExtensions 
{
公共静态布尔等于< T>(这件T左,T吧?)其中T:结构,IEquatable< T>
{
如果
返回false(left.HasValue!);

返回right.Equals(left.Value);
}
}



但是,调用它像这样:



 翻番? D = NULL; 
d.Equals(0.0);



调用到基等于(对象)拳击,因为你可以在IL看到:

  IL_0000:NOP 
IL_0001:ldloca.sd
IL_0003:initobj值类型[mscorlib程序] System.Nullable`1< float64>
IL_0009:ldloca.sð
IL_000b:ldc.r8 0.0
IL_0014:盒[mscorlib程序] System.Double
IL_0019:限制。值类型[mscorlib程序] System.Nullable`1< float64>
IL_001f:callvirt例如布尔[mscorlib程序] System.Object的::等于(对象)



如果我改变调用明确指出泛型类型:

  d.Equals<双>(0.0); 



它调用我的扩展方法:

  IL_0000:NOP 
IL_0001:ldloca.sd
IL_0003:initobj值类型[mscorlib程序] System.Nullable`1< float64>
IL_0009:ldloc.0
IL_000a:ldc.r8 0.0
IL_0013:调用布尔ConsoleApplication8.NullableExtensions ::等于< float64>(值类型[mscorlib程序] System.Nullable`1<!0 GT ;,!! 0)

为什么编译器不会选择在<$ C $扩展方法C>等于(对象)的方法?



是不是因为我只是选择了的一个贫穷的方法名称等于< T>(T)的地方其实不是的真实重载equals ,而不是继承查询的一部分?


解决方案

为什么编译器不会选择过的Equals(Object)方法的扩展方法?




扩展方法的只有的,如果没有其他选择考虑。这是一个回退 - 这是不正常的重载实例方法的一部分。这不是专门针对可空类型 - 这是正常的扩展方法调用的一部分



从规范的部分7.6.5.2:




在的形式



有一个

[...]


的方法调用

如果调用的正常处理没有发现适用的方法,试图处理结构作为扩展方法调用。




(重点煤矿。)


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

这篇关于T&gt;在可空&LT扩展方法;不叫除非泛型类型设置明确的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆