我将我的问题总结成以下代码片段。
List<int> list = new List<int>() { 5, 56, 2, 4, 63, 2 };
Console.WriteLine(list.First());
上述代码运行良好。
现在我尝试了下面的代码:
dynamic dList = list;
Console.WriteLine(dList.First());
但是我得到了 RuntimeBinderException 异常。为什么会这样?
对Jon的回答进行补充,这个问题不起作用的原因是因为在常规的非动态代码中,扩展方法通过对编译器已知的所有类进行全面搜索来工作,以查找具有匹配的扩展方法的静态类。搜索按照命名空间嵌套和每个命名空间中可用的using
指令的顺序进行。
这意味着为了正确解析动态扩展方法调用,DLR必须在运行时以某种方式知道您源代码中的所有命名空间嵌套和using
指令。我们没有一种机制可以将所有这些信息编码到调用站点中。我们考虑过发明这样的机制,但决定它成本太高,产生的进度风险也不值得。
dynamic
对象都等同于C#中的DynamicObject
,所以没有办法区分它们,这也是为什么不能向dynamic
添加扩展方法的原因之一,对吗? - Tomas Ramirez Sarduy在扩展Stecya的答案上... 扩展方法不支持以扩展方法的形式进行动态类型化,也就是说不能像调用实例方法一样去调用扩展方法。然而,这种方式可以正常工作:
dynamic dList = list;
Console.WriteLine(Enumerable.First(dList));
当然,那可能有用,如果你能提供更多关于为什么和如何使用动态类型的信息,我们或许可以提供更多帮助。dynamic
时才使用它……基本上,如果您否则将使用反射来访问成员,那么这是一个很大的提示。另一方面,我是一个顽固的静态类型支持者-其他人可能会建议不那么悲观的策略 :) - Jon Skeet因为First()
不是List
的一个方法,它是在Linq扩展中定义的,用于IEnumerable<>
this
在这里是动态的,但如果你来到这里,你可能也应该看看那个问题。 - nik.shornikov