【问题标题】:When passing dynamic to method, the result is dynamic expression, even if it is not将动态传递给方法时,结果是动态表达式,即使不是
【发布时间】:2014-10-29 04:21:14
【问题描述】:

在 C# 5 中,当我尝试将动态作为方法参数传递时,结果由于某种原因变为动态。

class Program
{
    static void Main(string[] args)
    {
        dynamic value = "John";
        Find<int>(value).ToList();
    }

    public static IEnumerable<T> Find<T>(object value)
    {
        //SOME LOGIC
        yield return default(T); //REAL RESULT
    }
}

Find&lt;T&gt;(value) 必须返回 IEnumerable&lt;T&gt;。 为什么编译器认为它是动态的?
我知道Find&lt;int&gt;(val as object).ToList(); 解决了这个问题,但我想了解为什么会发生这种情况。

【问题讨论】:

  • Eric Lippert 写了一篇很棒的博客 - Dynamic contagion, part one 和 Dynamic contagion, part two
  • @PatricHofman,我的意思是如果尝试在Find&lt;int&gt;(value) 后面加上点,你会看到一条消息 - '动态表达式。此操作将在运行时解决。`
  • @olegwx:好的。清除。从问题中错过了。
  • @petelids Eric Lippert 的文章自此移动:Dynamic contagion

标签: c# dynamic


【解决方案1】:

因为在运行时可能存在与 Find 之外的其他方法匹配的 Find,一旦您进入动态状态,一切都是动态的,包括确定适合的方法,因此一旦表达式中的某些内容是动态的,整个表达式就是动态的.

例如,可能有另一种方法,例如

public static T Find<T>(sometype value)
{
   return default T;
}

如果动态实际上是某种类型的类型,这将是运行时更好的匹配,因此只要编译器不知道动态是什么,它就无法推断返回类型,因为该类型可能是由在运行时最匹配的方法。

所以编译器说它返回动态,因为这是最好的选择,你的方法返回别的东西,但编译器还不知道那个方法是否会被调用。

【讨论】:

  • @PatrickHofman,@RonanThibaudau。谢谢罗南,此外,如果您尝试迭代他的结果var result = Find&lt;int&gt;(value); var list = result.ToList();,您将收到异常 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' 说“附加信息:'ConsoleApplication.Program.d__3'不包含“ToList”的定义”。是的,result is IEnumerable&lt;int&gt;; 是 true。最奇怪的事情...它不是编译时,它是运行时...
  • @olegwx 这也是意料之中的,虽然它可能看起来违反直觉。 ToList 是一个扩展方法,这意味着它实际上是 Enumerable.ToList(this IEnumerable item)。扩展方法依赖于类型信息,但也依赖于类型推断(知道 T 是什么并调用正确的 Generic 版本)。它根本与动态不兼容,总的来说你在那里滥用动态,它存在一些用例而linq不是其中之一,我强烈避免你做你希望对动态做的最低限度并在之后恢复为强类型,所有的 linq 都是基于类型和类型推断
【解决方案2】:

dynamic 在编译时是未知类型,但在运行时。所以在运行时它可以是字符串类型,并且可能有一个更好的匹配,称为 Find(string value),它返回不同的类型。这就是编译器无法告诉你的原因。它在运行时解决。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-11-23
    • 1970-01-01
    • 2021-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-10
    • 1970-01-01
    相关资源
    最近更新 更多