文章目錄
問題提出
由於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