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

我认为这是与类型的装箱和拆箱有关的某种问题?

4

1 回答 1

6

是的,就是这样。

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

创建一个匿名函数,其参数类型为Int32,返回值为,除了将参数转换为,并调用bool之外,什么都不做。就好像你写的objectMyFunc

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 回答