2012-12-31 41 views
2

假設下面的委託 「呼叫者」 簽名:拳擊和拆箱:爲什麼這個代表不匹配?

FuncCaller<T>(Func<T, bool> predicate) 

和匹配方法:

bool MyFunc(object o) 

T是引用類型,我可以調用MyFunc隱含像這樣:

FuncCaller<String>(MyFunc) // valid 

相反,當T是值類型,我打電話MYFUNC時含蓄地得到一個編譯錯誤:

FuncCaller<Int32>(MyFunc) // invalid ("No overload for 'MyFunc(object)' matches delegate 'System.Func<int?,bool>'") 

我的問題是,因爲這兩個例子,爲什麼是調用MyFunc無效的隱式調用時,但有效的調用時明確像這樣:

FuncCaller<Int32>(i => MyFunc(i)) // valid 

我認爲這是某種與拳擊和拆箱類型相關的問題?

回答

6

是的,就是這樣。

FuncCaller<Int32>(i => MyFunc(i)) // valid 

創建一個匿名函數,與Int32類型的參數,以及bool一個返回值,這不只是將參數轉換爲object,並調用MyFunc。這是因爲如果你寫

FuncCaller<Int32>(MyFunc2) 

其中MyFunc2被定義爲

bool MyFunc2(Int32 o) { return MyFunc(o); } 

轉換的參數是一個空操作,因此,沒有必要當類型爲引用類型,這就是爲什麼功能參數類型爲object對於參數類型爲string的代表已足夠接近:參數類型爲已經是object

轉換參數是一種真實的操作,當類型是一個值類型時不能被忽略。

值得指出的是,

FuncCaller<Int32>(MyFunc) 

是不是永遠簡寫

FuncCaller<Int32>(i => MyFunc(i)) 

即使它可能表現幾乎相同的方式。前者直接傳遞MyFunc函數,後者在其周圍創建一個包裝函數。這個包裝函數在這裏是必需的。