因为扩展方法绑定在编译时间。它们本质上被编译器转换为静态方法调用,这意味着
var result = test.ExtensionMethod(d);
被编译器转换为
var result = Program.ExtensionMethod(test, d);
When any的参数是dynamic
, then all绑定被推迟到运行时。运行时绑定器当前不支持扩展方法的绑定,编译器知道这一点,并会生成错误。
我什至会理解,如果我传递的是另一种动态之外的东西,调度是否会不起作用。
请记住dynamic
(like var
) 不是一个type。它只是意味着“我不知道这在编译时是什么类型 - 我会让动态运行时查看actual键入并确定如何处理它。
所以当你说:
dynamic d = new { World = "world" };
d
不是一个dynamic
"。在运行时,值d
将是匿名类型。
Could the dynamic binder support extension methods? Probably, but to date*, the added value has not been worth the cost (relative to other things that could be added) to design, implement, test, ship, and support such a feature. If you feel this would be a valuable addition to the framework, then feel free to submit a suggestion at http://connect.microsoft.com/ http://connect.microsoft.com/.
我还要注意的是,没有必要使用dynamic
在你的(尽管是人为的)场景中。如果您使用,您会得到完全相同的行为(具有扩展方法支持)object
代替dynamic
(并将扩展方法移至静态类):
public static string ExtensionMethod(this string format, object args)
{
return format + args.ToString();
}
private static void Main()
{
string test = "hello ";
object d = new { World = "world" };
// Error CS1973 'string' has no applicable method named 'ExtensionMethod'
// but appears to have an extension method by that name.
// Extension methods cannot be dynamically dispatched.
// Consider casting the dynamic arguments or calling
// the extension method without the extension method syntax.
var result = test.ExtensionMethod(d);
// this syntax works fine
var result2 = Program.ExtensionMethod(test, d);
// for whatever reason, this works, too!
var result3 = test.ExtensionMethod((object)d);
// even this works...
var result4 = test.ExtensionMethod(new { World = "world" });
Console.WriteLine(result);
Console.ReadLine();
}
* at least in 2011 problem of finding the method to call in this case was considered too hard - see Eric Lippert's answer - https://stackoverflow.com/a/5313149/477420 https://stackoverflow.com/a/5313149/477420: " ...That means that in order to get a dynamic extension method invocation resolved correctly, somehow the DLR has to know at runtime what all the namespace nestings and using directives were in your source code. We do not have a mechanism handy for encoding all that information into the call site..."