c# - 装箱和拆箱 : Why doesn't this delegate match?

标签 c# boxing anonymous-methods unboxing

假设以下委托(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/

相关文章:

c# - 当我的方法完成运行时,垃圾收集器会释放这个列表吗

C# 线程访问 if block ,其条件返回 false

c# - 如何获得第二个System.Thread.ThreadPool?

c# - 没有装箱的泛型方法中的原始类型转换

iphone - 是否可以在 Objective-C 中定义匿名选择器?

c# - 持久性 Cookie 在浏览器关闭时被删除 - Identity 2.0

java - 使用对象在java中自动装箱拆箱

c# - 如何在 C# 中返回通用列表集合?

c# - 不能在成员初始值设定项中使用 'this'?

c# - 装箱/拆箱是通过后期绑定(bind)还是早期绑定(bind)(即在运行时或编译时)实现的?