6

同じ名前空間とアセンブリにある次のいくつかの拡張メソッドがあります。

public static class DateTimeExtensions
{
    public static string NullSafeToString(this DateTime? possiblyNullDateTime, string format, string nullString = "")
}

public static class NullableExtensions
{
    public static string NullSafeToString<T>(this Nullable<T> nullable, string nullString = "") where T : struct
}

私の質問は、メソッドの解決についてです。次の呼び出し (別の名前空間から) は、ObjectExtensions.NullSafeToString予想どおりに解決されDateTimeExtensions.NullSafeToStringます。

DateTime? dateTime;
// ...
dateTime.NullSafeToString("yyyyMMdd");

オプションのパラメーターを から削除DateTimeExtensions.NullSafeToStringすると、期待どおりに解決されます。

C# 仕様のセクション 7.6.5.2 では、検索される名前空間の順序が概説されていますが、上記は同じ名前空間にあるため、セクション 7.6.5.1 の規則を使用すると予想されます。

私はそれが一致すると思っDateTimeExtensions.NullSafeToStringた:

  • どちらも の最初のパラメーターの型を持ちますがNullable<DateTime>、非ジェネリック メソッド (つまり、型パラメーターなし) が最初に考慮されると思いました。
  • パラメータリストは、最初にオプションのパラメータなしで考慮されると思いました

なぜそれがピッキングObjectExtensions.NullSafeToStringしているのか、誰でも明確にできますDateTimeExtensions.NullSafeToStringか?

(余談: ここでの他の議論から、逆参照を null セーフにするために拡張メソッドのセマンティクスを使用することに反対する人もいると思いますが、このような限られたシナリオで使用すると、より読みやすいコードになることがわかります。また、Nullable.ToString既にオブジェクト自体が null ではないため、null セーフですNullableが、含まれている へのパラメーターには対応していませんToString。また、明示的に名前が付けられたメソッドが null セーフの意図を示していることがわかりました。)

4

1 に答える 1

1

あなたの問題は拡張メソッドとは何の関係もありません。過負荷の解決とオプションのパラメーターについてです。(7.5.3c#仕様の過負荷の解決)このコードを試すことができます

public static string NullSafeToString(DateTime? possiblyNullDateTime, string format, string nullString = "")
    {
        return string.Empty;
    }
    public static string NullSafeToString<T>(Nullable<T> nullable, string nullString = "") where T : struct
    {
        return string.Empty;
    }
    static void Test()
    {
        DateTime? datetime = DateTime.Now;
        NullSafeToString(datetime, "yyyyMMdd");
    }
于 2012-05-25T09:40:40.800 に答える