C# 拳击及;拆箱:为什么不拆箱;这不是一场比赛吗?

C# 拳击及;拆箱:为什么不拆箱;这不是一场比赛吗?,c#,boxing,anonymous-methods,unboxing,C#,Boxing,Anonymous Methods,Unboxing,假设以下代理“调用方”签名: FuncCaller<T>(Func<T, bool> predicate) 当T是引用类型时,我可以像这样隐式调用MyFunc: 我的问题是,考虑到这两个示例,为什么隐式调用MyFunc时调用无效,但显式调用时有效,如下所示: FuncCaller(i=>MyFunc(i))//有效 我假设这是与类型的装箱和拆箱相关的某种问题?是的,这正是问题所在 FuncCaller<Int32>(i => MyFunc(i)) /

假设以下代理“调用方”签名:

FuncCaller<T>(Func<T, bool> predicate)
T
是引用类型时,我可以像这样隐式调用
MyFunc

我的问题是,考虑到这两个示例,为什么隐式调用
MyFunc
时调用无效,但显式调用时有效,如下所示:

FuncCaller(i=>MyFunc(i))//有效

我假设这是与类型的装箱和拆箱相关的某种问题?

是的,这正是问题所在

FuncCaller<Int32>(i => MyFunc(i)) // valid
其中
MyFunc2
定义为

bool MyFunc2(Int32 o) { return MyFunc(o); }
转换参数是不可操作的,因此当类型为引用类型时不需要转换参数,这就是为什么参数类型为
对象
的函数对于参数类型为
字符串
的委托足够接近的原因:参数类型已经是
对象

当类型为值类型时,转换参数是一个无法绕过的实际操作

值得指出的是

FuncCaller<Int32>(MyFunc)
FuncCaller(MyFunc)
从来都不是

FuncCaller<Int32>(i => MyFunc(i))
FuncCaller(i=>MyFunc(i))
即使它的行为方式几乎相同。前者直接传递
MyFunc
函数,后者在其周围创建一个包装函数。这个包装器函数在这里是必需的

FuncCaller<Int32>(i => MyFunc(i)) // valid
FuncCaller<Int32>(MyFunc2)
bool MyFunc2(Int32 o) { return MyFunc(o); }
FuncCaller<Int32>(MyFunc)
FuncCaller<Int32>(i => MyFunc(i))