T>在可空<扩展方法;不叫除非泛型类型设置明确 [英] Extension method on Nullable<T> not called unless generic type is set explicitly
问题描述
在调查另外一个问题:为什么有无可空< 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 genericEquals<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 ofEquals
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>在可空<扩展方法;不叫除非泛型类型设置明确的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!