具有可选参数的扩展方法中的方法解析

本文关键字:方法 扩展 参数 | 更新日期: 2023-09-27 18:35:14

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

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
}

我的问题是关于方法解析的。以下调用(来自另一个命名空间)在我预期DateTimeExtensions.NullSafeToString时解析为ObjectExtensions.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的参数,我发现显式命名的方法指示空安全意图。

具有可选参数的扩展方法中的方法解析

您的问题与扩展方法无关。这是关于重载分辨率和可选参数。(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");
    }