假设以下委托(delegate)“调用者”签名:
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
我认为这是与类型的装箱和拆箱相关的某种问题?
最佳答案
是的,就是这样。
FuncCaller<Int32>(i => MyFunc(i)) // valid
创建一个匿名函数,参数类型为Int32
,返回值为bool
,除了将参数转换为object
,并调用 MyFunc
。就好像你写了
FuncCaller<Int32>(MyFunc2)
其中 MyFunc2
定义为
bool MyFunc2(Int32 o) { return MyFunc(o); }
转换参数是空操作,因此当类型是引用类型时不需要,这就是为什么参数类型为 object
的函数对于具有参数类型的委托(delegate)足够接近的原因string
:参数类型已经是一个object
。
参数转换是真正的操作,当类型是值类型时是无法绕过的。
值得一提的是
FuncCaller<Int32>(MyFunc)
永远不是
的简写FuncCaller<Int32>(i => MyFunc(i))
即使它的行为方式几乎相同。前者直接传递 MyFunc
函数,后者围绕它创建一个包装函数。包装函数在这里是必需的。
关于c# - 装箱和拆箱 : Why doesn't this delegate match?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14106540/