为什么动态IEnumerable上的First()或ElementAt()是等待的?

时间:2015-10-09 09:16:53

标签: c# linq asynchronous dynamic async-await

我正在使用Dapper并让它返回动态IEnumerable,如下所示:

var rows = conn.Query("SELECT * FROM T WHERE ID = @id", new { id = tableId });
var row = rows.FirstOrDefault();

此处rows的类型为IEnumerable<dynamic>。 IntelliSense说FirstOrDefault()是可以等待的,并且使用await FirstOrDefault()。并非所有LINQ查询都显示为等待,但似乎特别是那些单独输出元素的那些。

一旦我使用强类型,这种行为就会消失。

是不是因为.NET无法知道您在运行时接收的类型是否可以接受,因此它允许&#34;允许&#34;它,如果你需要它?但是没有强制执行吗?或者我应该,由于一些动态语言运行时行为,实际上在这里使用await

我一直在搜索,但没有在网上找到最小的东西。

1 个答案:

答案 0 :(得分:8)

编译器的

async-await功能取决于Duck Typing。所以有方法GetAwaiter(实例或扩展方法)返回实现INotifyCompletion接口的类型并具有下一个字段的所有内容:

  • bool IsCompleted { get; }
  • void|TResult GetResult()

可以等待。

您可以在编译时(从docs)调用动态类型上的任何内容:

  

在编译时,假定键入为动态的元素支持任何操作。

这就是编译器在编译时没有显示任何警告/错误的原因,但在运行时,您将获得类似于以下内容的异常:

  

RuntimeBinderException。

     

'&lt;&gt; f__AnonymousType0'不包含'GetAwaiter'的定义

如果指定显式类型,编译器将搜索方法GetAwaiter。然后,如果您的强类型不包含它,您将收到编译时错误。

所以,你的问题的答案确实是因为dynamic特殊行为。