尝试将您的Worker
课程更改为:
public class Worker
{
public void DoSomething(ICallBack cb)
{
((dynamic)cb).Handle(55);
}
}
[编辑]
正如您所知,添加看起来无害的“动态”会严重改变输出代码。它在运行时有效地调用编译器来做动态的事情。
我还提请您注意这里的评论和其他答案。我建议您阅读它们并理解为什么执行上述操作可能不是一个好主意。
此外,如以下答案中所述,如果显式实现该方法,则将参数类型限制为ICallBack
仍将允许运行时错误。Handle()
这是那个看起来很简单的方法的 IL:
.method public hidebysig instance void DoSomething(class ConsoleApplication1.ICallBack cb) cil managed
{
.maxstack 9
.locals init (
[0] class [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo[] CS$0$0000)
L_0000: nop
L_0001: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Action`3<class [System.Core]System.Runtime.CompilerServices.CallSite, object, int32>> ConsoleApplication1.Worker/<DoSomething>o__SiteContainer0::<>p__Site1
L_0006: brtrue L_0058
L_000b: ldc.i4 256
L_0010: ldstr "Handle"
L_0015: ldnull
L_0016: ldtoken ConsoleApplication1.Worker
L_001b: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
L_0020: ldc.i4.2
L_0021: newarr [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo
L_0026: stloc.0
L_0027: ldloc.0
L_0028: ldc.i4.0
L_0029: ldc.i4.0
L_002a: ldnull
L_002b: call class [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo::Create(valuetype [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags, string)
L_0030: stelem.any [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo
L_0035: ldloc.0
L_0036: ldc.i4.1
L_0037: ldc.i4.3
L_0038: ldnull
L_0039: call class [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo::Create(valuetype [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags, string)
L_003e: stelem.any [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo
L_0043: ldloc.0
L_0044: call class [System.Core]System.Runtime.CompilerServices.CallSiteBinder [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.Binder::InvokeMember(valuetype [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags, string, class [mscorlib]System.Collections.Generic.IEnumerable`1<class [mscorlib]System.Type>, class [mscorlib]System.Type, class [mscorlib]System.Collections.Generic.IEnumerable`1<class [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo>)
L_0049: call class [System.Core]System.Runtime.CompilerServices.CallSite`1<!0> [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Action`3<class [System.Core]System.Runtime.CompilerServices.CallSite, object, int32>>::Create(class [System.Core]System.Runtime.CompilerServices.CallSiteBinder)
L_004e: stsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Action`3<class [System.Core]System.Runtime.CompilerServices.CallSite, object, int32>> ConsoleApplication1.Worker/<DoSomething>o__SiteContainer0::<>p__Site1
L_0053: br L_0058
L_0058: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Action`3<class [System.Core]System.Runtime.CompilerServices.CallSite, object, int32>> ConsoleApplication1.Worker/<DoSomething>o__SiteContainer0::<>p__Site1
L_005d: ldfld !0 [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Action`3<class [System.Core]System.Runtime.CompilerServices.CallSite, object, int32>>::Target
L_0062: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Action`3<class [System.Core]System.Runtime.CompilerServices.CallSite, object, int32>> ConsoleApplication1.Worker/<DoSomething>o__SiteContainer0::<>p__Site1
L_0067: ldarg.1
L_0068: ldc.i4.s 12
L_006a: callvirt instance void [mscorlib]System.Action`3<class [System.Core]System.Runtime.CompilerServices.CallSite, object, int32>::Invoke(!0, !1, !2)
L_006f: nop
L_0070: ret
}