2013-02-15 36 views
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更好的函数成员第一鉴别要应用是:

  • 如果MP和MQ的一个不通用,但其他是通用的,那么非通用更好。

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

+0

你在看C#4.0规范吗?我怀疑你正在查看一个较旧的规范,它没有提及可选参数,因为那些只是在C#4.0中引入的。 – CodesInChaos 2013-02-15 13:08:19

+0

我相信你的方法有不同的签名。你是否尝试过,例如传递int或其他东西? – 2013-02-15 13:09:22

+0

@Codes:我没有,但4.0规范说了同样的事情,只是它在7.5.3.2。 – 2013-02-15 13:11:30

回答

8

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

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

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

参考文献:

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

    作为决胜规则,对于这其中明确给出的所有参数优于一个为函数成员默认值是用来代替明确的参数。

  2. MSDN,标题为“超载决议”,最后一个项目符号点:

    如果两个候选人被判断为一样好,偏好去不有哪些参数是可选参数的候选在通话中省略。这是因为参数较少的候选人在重载分辨率方面普遍偏好的结果。

  3. The C# Language Specification,章节 “7.5.3.2更好函数成员”:

    • 扩展形式:

      对于每个候选功能的部件以下面的方式构造的参数列表如果函数成员仅适用于扩展形式,则使用该函数。

    • 没有对应参数可选参数从参数列表移除

    它继续这样的:

    鉴于与一组参数表达式的参数列表A {ë ,E ,...,E Ñ}和两个适用函数成员MP和MQ与参数类型{P ,P ,...,P Ñ}和{Q ,Q 。 ..,Q ñ} [...]

    此时与可选的参数的方法是已经退出游戏。 N是1,但该方法有两个参数。

+0

你能引用规范来支持它吗?即必须替代可选参数的默认值比不得不使用通用方法更糟糕? – CodesInChaos 2013-02-15 13:13:22

+0

@CodesInChaos:请参阅更新。 – 2013-02-15 13:13:45

+0

oO为什么他们将4.0的功能放入单独的草稿文档中?正常的C#4。0规范不包含这些章节。 – CodesInChaos 2013-02-15 13:20:17

3

docs说:

如果两个候选人被判断为一样好,偏好去不有哪些参数是在调用省略可选参数的候选人。这是因为参数较少的候选人在重载分辨率方面普遍偏好的结果。

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

1

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

从概念上说,将运行pre v4中的方法重载分辨率。如果发现匹配匹配将被使用。 (概念,因为这不是它是如何工作的描述,但你能怎么想的吧)

你的情况,发现只有一个比赛是你的泛型方法

如果没有找到匹配它的外观对于具有部分匹配的方法以及可以使用默认值完成匹配的方法。在你的情况下,你会发现在这次运行中没有一个通用的方法,但是由于已经找到了一个匹配,所以分辨率从未达到这个目标。

删除第二个参数时,最终会出现泛型和非泛型匹配的情况。你选择非规范化的规则。

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

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

相关问题