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

Posted

技术标签:

【中文标题】带有可选参数的扩展方法中的方法解析【英文标题】:Method resolution in extension methods with optional parameters 【发布时间】:2012-05-25 09:12:30 【问题描述】:

我有以下几个扩展方法,它们在同一个命名空间和程序集中:

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&lt;DateTime&gt;,但我认为应该首先考虑非泛型方法(即没有类型参数)。 虽然参数列表会在没有可选参数的情况下首先考虑

谁能澄清为什么选择ObjectExtensions.NullSafeToString 而不是DateTimeExtensions.NullSafeToString

(除此之外:从这里的其他讨论中,我怀疑有些人可能不赞成使用扩展方法语义来使解除引用 null 安全,但我发现用于像这样的有限场景,它们使代码更具可读性。另外我知道Nullable.ToString 已经是空安全的,因为Nullable 对象本身不是空的,但这不适合包含的ToString 的参数,我发现显式命名的方法表明空安全意图.)

【问题讨论】:

重载解析应用“更少的参数 == 更好”。 【参考方案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");
    

【讨论】:

感谢您的回复。我仍然不清楚为什么它选择 ObjectExtensions.NullSafeToString 而不是 DateTimeExtensions.NullSafeToString。从 7.5.3.1 开始:“如果 MP 是非泛型方法而 MQ 是泛型方法,则 MP 优于 MQ”。我想其他一些规则会首先发挥作用,但我不确定是哪一个。 对不起 - 那应该是 7.5.3.2 “更好的功能成员”。

以上是关于带有可选参数的扩展方法中的方法解析的主要内容,如果未能解决你的问题,请参考以下文章

带有多级解析器/子解析器的 Argparse 可选参数

Python 选项解析器:带有可选参数的布尔标志

重载的方法在 Resharper 中给出“带有可选参数的方法被重载隐藏”警告

字符串扩展,添加一个方法“add”并将一个 Int 作为没有标签的参数并返回一个可选的 Int

Mathematica 中的可选命名参数

Go/可选参数中的多个构造函数?