[c#美味] c#4中默认参数和命名参数后的函数重载

问题提出

由于C#4中新增了默认参数和命名参数,导致函数重载的情况变得比以前复杂了一些。

举例如下,假设有下面4个函数:

static void Fun(string name, int num = 1) 
{
}

static void Fun(object o)
{
}

static void Fun(int num, string name = "Greenerycn") 
{
}

static void Fun(int num)
{
}
调用的代码如下:

static void Main(string[] args)
{
    Fun(99);
}

那么这会调用哪个函数呢?

 

重载决策规则

什么是重载决策呢?根据MSDN提供的资料:

重载决策是一种编译时机制,用于在给定了参数列表和一组候选函数成员的情况下,选择一个最佳函数成员来实施调用。

使用命名实参和可选实参将在以下方面对重载决策产生影响:

  • 如果方法、索引器或构造函数的各个形参均为可选,或者按名称或位置与调用语句中的单个实参对应,并且该实参可转换为形参的类型,则该方法、索引器或构造函数是执行的候选项。

  • 如果找到多个候选项,则会将首选转换的重载决策规则应用于显式指定的实参。将忽略可选形参已省略的实参。

  • 如果两个候选项不相上下,则会将没有可选形参的候选项作为首选项,对于这些可选形参,已在调用中为其省略了实参。这是具有较少形参的候选项的重载决策中一般首选项的结果。

英文的如下:

  • A method, indexer, or constructor is a candidate for execution if each of its parameters either is optional or corresponds, by name or by position, to a single argument in the calling statement, and that argument can be converted to the type of the parameter.

  • If more than one candidate is found, overload resolution rules for preferred conversions are applied to the arguments that are explicitly specified. Omitted arguments for optional parameters are ignored.

  • If two candidates are judged to be equally good, preference goes to a candidate that does not have optional parameters for which arguments were omitted in the call. This is a consequence of a general preference in overload resolution for candidates that have fewer parameters.

上面这段规则太拗口了。。。不管是英文的还是中文的都不好理解。还是按上面的例子来说明吧。

 

实例分析

 

调用函数:Fun(99)

实参:99, 类型int

实参个数:1

 

Fun的重载函数总共有4个,我们一一分析:

Fun(string name, int num = 1)

根据规则1,它的第一个参数name类型是string和99即int类型不匹配,而且name也不是有默认值可省略的参数,所以它不能列为候选。

 

Fun(object o)

根据规则1,因为int类型是可以转换为object类型的,而且参数个数也相同,列为候选。

 

Fun(int num, string name = "Greenerycn")

根据规则1,因为num是int类型,99也是int类型,而且name是有默认值可省略的参数,所以也列为候选。

 

Fun(int num)

根据规则1,因为num是int类型,99也是int类型,两个类型相同,也没有其他的行参,故列为候选。

 

这样看来,我们就有3个候选了,即:

Fun(object o)

Fun(int num, string name = "Greenerycn")

Fun(int num)

 

现在要处理多个候选的情况,按照重载的一般规则(http://msdn.microsoft.com/zh-cn/vstudio/aa691338(VS.71).aspx),即转换好的优先。那么

Fun(object o)

就被淘汰出局,因为99是int类型,int转换为int显然比转换为object好。

 

ok,现在还有两个:

Fun(int num, string name = "Greenerycn")

Fun(int num)

 

根据规则3,优先选择没有可选形参的函数。最终得出匹配的函数是:

Fun(int num)

 

即:Fun(99) 实际上调用的是Fun(int num)  这个函数。

 

我现在还没找到规则2的例子,等找到后再完善这篇文章吧。

 

参考资料:

Named and Optional Arguments (C# Programming Guide)

http://msdn.microsoft.com/en-us/library/dd264739.aspx

命名实参和可选实参(C# 编程指南)

http://msdn.microsoft.com/zh-cn/library/dd264739.aspx

New features in CSharp 4.0.doc

http://code.msdn.microsoft.com/cs2010samples/Release/ProjectReleases.aspx?ReleaseId=4175

C# 语言规范:7.4.2 重载决策

http://msdn.microsoft.com/zh-cn/vstudio/aa691336(VS.71).aspx

使用索引器(c#编程指南)

http://msdn.microsoft.com/zh-cn/library/2549tw02.aspx

Named arguments and overload resolution:

http://blogs.msdn.com/b/samng/archive/2009/04/01/named-arguments-and-overload-resolution.aspx

posted @ 2010-05-30 19:06  林杰的博客  阅读(2617)  评论(0编辑  收藏  举报