別の質問を調査しているときに、「 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
なく、継承ルックアップの一部ではない、貧弱なメソッド名を選択したからですか?