【问题标题】:Extension method and dynamic object扩展方法和动态对象
【发布时间】:2011-07-15 18:01:19
【问题描述】:

我将把我的问题总结成下面的代码sn-p。

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

以上代码运行良好。

现在我尝试了以下

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

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

【问题讨论】:

标签: c# dynamic c#-4.0


【解决方案1】:

为了扩展 Jon 的答案,这不起作用的原因是因为在常规的非动态代码扩展方法中,通过对编译器已知的所有类进行全面搜索来查找具有扩展方法的静态类匹配。搜索根据命名空间嵌套和每个命名空间中可用的using 指令按顺序进行。

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

【讨论】:

  • 非常感谢您的解释。
  • 即将推出这样的功能吗?这肯定是一个突破性的变化。当前抛出 RunTimeBinderExceptions 的调用会在重新编译源代码时突然开始工作。此外,实施此类功能是否存在任何安全风险?
  • @ani:我们是否计划实施该功能? 没有。有任何安全风险吗?我不知道;您想到了什么样的安全风险?首先说明谁是攻击者以及他们对用户造成的威胁。
  • @EricLippert,我知道所有dynamic对象都等于C#:DynamicObject,所以没有办法区分它们,这也是无法添加扩展方法的原因之一到dynamic,对吗?
  • @EricLippert 考虑进一步扩展这个答案并添加句子“当 any 的参数是动态的,那么所有的解决方案都被推迟到运行时”。虽然对您来说很明显这一重要部分很难在 SO 上的其他任何地方找到(例如,请参阅 stackoverflow.com/questions/48324768)
【解决方案2】:

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

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

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

【讨论】:

  • 我在玩动态对象时遇到了这个异常。你有没有写过关于这个主题的文章,在哪里使用或不使用动态对象
  • @geek:就我个人而言,我的经验法则是仅在您真正需要的地方使用dynamic...基本上,如果您要通过反射访问成员,这是一个很大的迹象。另一方面,我是一个顽固的静态打字员 - 其他人可能会建议不那么悲观的政策:)
  • 转换回已知类型可能更具可读性,这可行: Console.WriteLine(((List)dList).First());或 Console.WriteLine((dList as List).First());.
【解决方案3】:

因为First() 不是List 的方法。它在 Linq 扩展中定义为 IEnumerable&lt;&gt;

【讨论】:

    猜你喜欢
    • 2011-05-31
    • 1970-01-01
    • 2015-08-27
    • 1970-01-01
    • 1970-01-01
    • 2013-01-18
    • 2018-07-03
    • 1970-01-01
    相关资源
    最近更新 更多