我将我的问题总结为以下代码段。

List<int> list = new List<int>() { 5, 56, 2, 4, 63, 2 };
Console.WriteLine(list.First());


上面的代码可以正常工作。

现在我尝试了以下

dynamic dList = list;
 Console.WriteLine(dList.First());


但是我遇到了RuntimeBinderException。为什么会这样?

评论

这似乎是仅在4天前问这个问题的重复项stackoverflow.com/questions/5270782/…

@jbtule的区别在于,这在这里是动态的,但是如果您落在这里,您可能也应该看看该问题

C4中的动态关键字几乎将支持扩展方法

#1 楼

为了扩展Stecya的答案...扩展类型不受扩展方法形式的动态类型的支持,即像它们是实例方法一样被调用。但是,这将起作用:

dynamic dList = list;
Console.WriteLine(Enumerable.First(dList));


当然,这可能有用也可能没有用。如果您可以提供有关为什么以及如何尝试使用动态类型的更多信息,我们可能会提供更多帮助。

评论


我在玩动态对象时遇到了这个异常。您是否写过关于此主题的任何文章,在何处使用或不使用动态对象?

–santosh singh
2011-3-15在12:27



@geek:就我个人而言,我的经验法则只是在您真正需要的地方使用动态...基本上,如果您否则将通过反思来访问成员,那是一个很大的信号。另一方面,我是一个顽固的静态打字员-其他人可能会建议一些不太悲观的政策:)

–乔恩·斯基特(Jon Skeet)
2011-3-15在12:36

强制转换回已知类型可能更易读,这可以正常工作:Console.WriteLine((((List )dList).First());或Console.WriteLine((dList as List )。First());。

– AVee
19 Jun 18 '13:46



#2 楼

为了扩展Jon的答案,之所以不起作用,是因为在常规的非动态代码扩展方法中,通过对编译器已知的所有类进行完整搜索,以查找具有匹配的扩展方法的静态类,从而可以正常工作。搜索是根据名称空间嵌套和每个名称空间中可用的using指令进行的。

这意味着为了正确解决动态扩展方法调用,DLR必须在运行时以某种方式知道源代码中所有名称空间嵌套和using指令是什么。我们没有方便的机制将所有这些信息编码到呼叫站点中。我们曾考虑发明这样一种机制,但认为它成本太高,产生了太多的进度风险,因此不值得。

评论


非常感谢您的解释。

–santosh singh
2011-03-15 14:47

即将推出这样的功能吗?这肯定是一个重大变化。当前引发RunTimeBinderExceptions的调用将在重新编译源代码时突然开始工作。另外,实施此功能会不会有安全隐患?

–阿尼
2011-3-15在23:45

@ani:我们打算实现该功能吗?否。是否存在安全风险?我什么都不知道;您想到了什么样的安全风险?首先说明谁是攻击者,以及他们对用户造成的威胁。

–埃里克·利珀特
2012年2月1日于16:08

@EricLippert,我已经了解到所有动态对象都等于C#:DynamicObject,因此无法区分它们,这也是为什么无法向动态添加扩展方法的原因之一,对吗?

–汤姆·萨杜(Tom Sarduy)
2012-10-28 17:25

@EricLippert考虑进一步扩展此答案,并按照“当任何参数是动态的时,所有分辨率都推迟到运行时”的句子添加句子。尽管对您来说很明显,但是在SO上的其他任何地方都很难找到这一重要点(例如,请参见stackoverflow.com/questions/48324768)

–阿列克谢·莱文科夫(Alexei Levenkov)
18年1月18日在16:12



#3 楼

因为First()不是List的方法。它在IEnumerable<>的Linq扩展中定义