以下代码段
static class Program
{
public static void Main()
{
dynamic data = "0001010";
var value = System.Convert.ToInt64(data);
System.Console.Out.WriteLine(value.DoubleIt());
}
static long DoubleIt(this long source)
{
return source * 2;
}
}
失败
Unhandled Exception: Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'long' does not contain a definition for 'DoubleIt'
at CallSite.Target(Closure , CallSite , Object )
at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)
at Program.Main()
虽然改变了一点
long value = System.Convert.ToInt64(data);
或
string data = "0001010";
足以使这项工作。
看看IL,看来前者试图通过反射加载DoubleIt,而后者则导致DoubleIt静态绑定。
为什么会出现这种情况?
答案 0 :(得分:2)
因为value
实际上是dynamic
。在编译时,我们实际不知道正在调用哪个System.Convert.ToInt64
方法 - 它可能是任何重载(如果有的话)。
因此,您需要明确说value
是long
。这告诉编译器你知道你在做什么,如果你不知道你会得到一个运行时错误(例如,如果ToInt64
返回了string
)。或者,您可以删除动态调用(通过将dynamic
替换为string
来执行此操作) - 此时我们知道完全正在调用哪个ToInt64
方法
当您编写DoubleIt()
时 - 您实际上并未绑定到扩展方法。 dynamic
并不关心你写的是什么,并会尝试在运行时将其解析为对象本身的一种方法 - 并且不考虑扩展方法
扩展方法只是语法糖,并在IL中编译为:
SomeStaticClass.DoubleIt(value)
这使得为什么无法运行value.DoubleIt()