使用可选参数的扩展方法中的方法解析

时间:2012-05-25 09:12:31

标签: c# .net extension-methods resolution optional-parameters

我有以下几种扩展方法,它们位于相同的命名空间和程序集中:

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已经是空安全的,因为Nullable对象本身不为空,但是它不能满足包含ToString的参数,我发现明确命名的方法表示无效的意图。)

1 个答案:

答案 0 :(得分:1)

您的问题与扩展方法无关。它是关于重载分辨率和可选参数。(7.5.3 c#规范的重载分辨率) 您可以尝试此代码

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");
    }