扩展方法和动态对象

san*_*ngh 93 c# dynamic c#-4.0

我将把我的问题总结为以下代码片段.

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

上面的代码工作正常.

现在我尝试了以下内容

dynamic dList = list;
 Console.WriteLine(dList.First());
Run Code Online (Sandbox Code Playgroud)

但是我得到了RuntimeBinderException.为什么会这样?

Eri*_*ert 134

为了扩展Jon的答案,这不起作用的原因是因为在常规的非动态代码扩展方法中,通过对编译器已知的所有类的完整搜索来工作,该静态类具有匹配的扩展方法.搜索按顺序排列,基于using每个命名空间中的命名空间嵌套和可用指令.

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

  • @ani:**我们是否计划实施该功能?**否**是否有任何安全风险?**我不知道任何风险?你有什么样的安全风险?首先说明攻击者是谁以及他们对用户造成的威胁. (5认同)
  • 即将到来的这样一个功能?这肯定是一个突破性的变化; 当前抛出RunTimeBinderExceptions的调用会在重新编译源时突然开始工作.此外,实施此功能是否存在任何安全风险? (3认同)

Jon*_*eet 125

扩展Stecya的答案......扩展方法形式的动态类型不支持扩展方法,即调用它们就像实例方法一样.但是,这将有效:

dynamic dList = list;
Console.WriteLine(Enumerable.First(dList));
Run Code Online (Sandbox Code Playgroud)

当然,这可能有用也可能没用.如果您可以提供有关您尝试使用动态类型的原因和方式的更多信息,我们可以提供更多帮助.

  • @geek:就个人而言,我的经验法则只是使用`dynamic`你真正需要的地方......基本上如果你不能用反射来访问成员,那就是一个大问题.另一方面,我是一个顽固的静态typer - 其他人可能会建议不那么悲观的政策:) (19认同)
  • 转换回已知类型可能更具可读性,这有效: Console.WriteLine(((List&lt;int&gt;)dList).First()); 或 Console.WriteLine((dList as List&lt;int&gt;).First());。 (2认同)

Ste*_*cya 18

因为First()不是方法List.它在Linq Extension中定义为IEnumerable<>