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>'")

私の質問は、これら2つの例を考えると、MyFunc暗黙的に呼び出された場合は無効の呼び出しであるのに、次のように明示的に呼び出された場合は有効である理由です。

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

これは、タイプのボックス化とボックス化解除に関連するある種の問題だと思いますか?

4

1 に答える 1

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後者はその周りにラッパー関数を作成します。そのラッパー関数はここで必要です。

于 2012-12-31T22:40:01.757 に答える