在调查另一个问题时:“Why there is no Nullable<T>.Equals(T value) method?”我在Nullable<T>
上制作了一个展示通用Equals<T>(T)
方法的扩展方法:
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);
}
}
然而,这样称呼它:
double? d = null;
d.Equals(0.0);
使用拳击调用基础Equals(object)
,如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)
如果我将调用更改为显式声明泛型类型:
d.Equals<double>(0.0);
它调用我的扩展方法:
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)
为什么编译器没有选择Equals(object)
方法的扩展方法?
是不是因为我刚刚选择了一个不好的Equals<T>(T)
方法名称,它实际上并不是Equals
的真正覆盖而不是继承查找的一部分?
答案 0 :(得分:9)
为什么编译器没有选择Equals(object)方法的扩展方法?
如果没有其他替代方案,则仅考虑扩展方法 。这是一个后备 - 它不是实例方法的正常重载分辨率的一部分。这不是特定于可空类型 - 它是正常扩展方法调用的一部分。
来自规范的第7.6.5.2节:
在方法中调用其中一种形式
[...]
如果调用的正常处理找不到适用的方法,则尝试将构造作为扩展方法调用进行处理。
(强调我的。)