在调查另一个问题时:“为什么没有 Nullable<T>.Equals(T value) 方法? ”我做了一个扩展方法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
而不是继承查找的一部分吗?