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