为什么选择泛型函数成员而不是非泛型函数?

时间:2013-02-15 13:04:20

标签: c# .net

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

打印“Generic”。删除, EnumTest t = EnumTest.EnumEntry会使其打印为“正常”。

然而标准似乎很清楚,从 14.4.2.2更好的功能成员应用的第一个鉴别器是:

  • 如果MP和MQ中的一个是非泛型的,但另一个是通用的,那么非泛型更好。

我是否遗漏了某些内容或编译错误?

3 个答案:

答案 0 :(得分:8)

你错过了什么。这就是以下内容:

您使用一个参数调用该方法。只有一种方法有一个参数,即通用参数。这就是所选择的那个。

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

<强>参考文献:

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

      

    作为一个平局规则,一个函数成员,其中显式给出的所有参数都优于提供默认值的参数,而不是显式参数。

  2. MSDN,标题为“重载决议”,最后一个要点:

      

    如果两个候选人被判断为同样好,则优先选择没有可选参数的候选人,其中参数在呼叫中被省略。这是对具有较少参数的候选者的重载分辨率的一般偏好的结果。

  3. The C# Language Specification,章节“7.5.3.2更好的功能成员”:

      

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

         
        
    • 如果功能成员仅适用于展开的表单,则使用展开的表单。
    •   
    • 从参数列表
    • 中删除没有相应参数的可选参数   

    它继续这样:

      

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

    此时,带有可选参数的方法已经不在游戏中了。 N为1,但该方法有两个参数。

答案 1 :(得分:3)

docs说:

  

如果两个候选人被判断为同样好,则优先选择没有可选参数的候选人,其中参数在呼叫中被省略。这是对具有较少参数的候选者的重载分辨率的一般偏好的结果。

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

答案 2 :(得分:1)

使用方法参数的默认值,可以扩展重载决策。

从概念上讲,将运行v4之前的方法重载决策。如果找到匹配的匹配项将被使用。 (从概念上讲,因为这不是对它如何工作的描述,而是你如何能想到它)

在您的情况下,它只找到一个匹配作为您的通用方法

如果找不到匹配项,它将查找具有部分匹配的方法以及可以使用默认值完成匹配的方法。在你的情况下,你可以在这次运行中找到无结果方法,但是由于已经找到匹配,因此分辨率永远不会出现。

删除第二个参数时,最终会出现通用匹配和非通用匹配的情况。而且你在挑选非泛型的时候会采取这样的规则。

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

匹配的非泛型方法比泛型更具体,因为类型不能改变。 使用默认参数的方法不如参数计数与参数计数匹配的方法(数字是精确匹配) 如果两个方法可用,但是一个接受IFoo的参数而另一个接受Foo(实现IFoo),则在将Foo对象作为参数传递时将选择后者,因为它是完全匹配的Ie。更具体的