9
public enum EnumTest
{
    EnumEntry
}

public class TestClass
{
    public string FunctionMember(string s, EnumTest t = EnumTest.EnumEntry)
    {
        return "Normal";
    }

    public string FunctionMember<T>(T t)
    {
        return "Generic";
    }
}

class Program
{
    static void Main(string[] args)
    {
        TestClass t = new TestClass();

        Console.WriteLine(t.FunctionMember("a"));
    }
}

这将打印“通用”。删除, EnumTest t = EnumTest.EnumEntry使其打印“正常”。

然而标准似乎很明确,从14.4.2.2 Better function member开始应用的第一个鉴别器是:

  • 如果 MP 和 MQ 之一是非泛型,而另一个是泛型​​,则非泛型更好。

我错过了什么或编译器错误吗?

4

3 回答 3

8

你错过了一些东西。这就是以下内容:

您使用一个参数调用该方法。只有一种方法具有一个参数,即泛型方法。所以这就是被选中的那个。

只有当它没有找到匹配的方法时,它才会查看带有可选参数的其他方法。

参考:

  1. C# 4.0 规范,21.4 中的最后一段:

    作为一个决胜局规则,一个函数成员,所有显式给出的参数都比一个提供默认值代替显式参数的函数成员要好。

  2. MSDN,标题“重载分辨率”,最后一个要点:

    如果两个候选者被判断为同样好,则优先考虑没有可选参数的候选者,在调用中省略了这些参数。这是对具有较少参数的候选者的重载解决方案的普遍偏好的结果。

  3. C# 语言规范,章节“7.5.3.2 更好的函数成员”:

    每个候选函数成员的参数列表按以下方式构造:

    • 如果函数成员仅适用于扩展形式,则使用扩展形式。
    • 从参数列表中删除没有对应参数的可选参数

    它继续这样:

    给定一个带有一组参数表达式 { E 1 , E 2 , ..., E N } 的参数列表 A 和两个具有参数类型 { P 1 , P 2 , ..., P N }的适用函数成员 MP 和 MQ和 { Q 1 , Q 2 , ..., Q N } [...]

    此时带有可选参数的方法已经出局了。N是 1,但该方法有两个参数。

于 2013-02-15T13:08:34.493 回答
3

文档说:

如果两个候选者被判断为同样好,则优先考虑没有可选参数的候选者,在调用中省略了这些参数。这是对具有较少参数的候选者的重载解决方案的普遍偏好的结果。

换句话说,没有任何可选参数的方法将是首选。

于 2013-02-15T13:13:00.983 回答
1

使用方法参数的默认值,重载分辨率得到了扩展。

从概念上讲,将运行 v4 之前的方法重载解析。如果找到匹配项,则将使用该匹配项。(从概念上讲,因为这不是描述它是如何工作的,而是描述你如何思考它)

在您的情况下,它恰好找到一个匹配项是您的通用方法

如果没有找到匹配项,它将查找具有部分匹配项的方法,并且可以使用默认值完成匹配项。在您的情况下,将在此运行中找到您的非泛型方法,但是由于已经找到匹配项,因此解决方案永远不会走到这一步。

删除第二个参数时,您最终会遇到通用和非通用匹配的情况。并且您引用的规则开始选择非通用。

总而言之,一个好的经验法则是选择最具体的可用方法。

匹配的非泛型方法比泛型更具体,因为类型不能改变。如果有两种方法可用,但一种采用 IFoo 的参数,另一种采用 Foo(实现 IFoo),则具有默认参数的方法不如参数计数与参数计数匹配(数字完全匹配)的方法具体将 Foo 对象作为参数传递时将选择后者,因为它是完全匹配的即。更详细

于 2013-02-15T13:15:39.833 回答