2015-10-09 10 views
6

Tôi đã sử dụng Dapper và có nó trả về một IEnumerable động, như thế này:Tại sao First() hoặc ElementAt() trên một IEnumerable động đang chờ?

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

Ở đây, rows là loại IEnumerable<dynamic>. Các IntelliSense nói FirstOrDefault() là awaitable, và có cách sử dụng await FirstOrDefault(). Không phải tất cả các truy vấn LINQ đều được hiển thị là có thể chờ đợi, nhưng có vẻ như đặc biệt là các truy vấn đơn lẻ.

Ngay khi tôi sử dụng gõ mạnh, hành vi này biến mất.

Có phải vì .NET không biết liệu kiểu bạn nhận được trong thời gian chạy có đang chờ hay không, sao cho nó "cho phép" trong trường hợp bạn cần? Nhưng không thực thi nó? Hoặc tôi phải, do một số hành vi thời gian chạy ngôn ngữ động, thực sự sử dụng await ở đây?

Tôi đã tiếp tục tìm kiếm nhưng không tìm thấy điều nhỏ nhất về trực tuyến này.

+0

bạn có thể chờ đợi từ sự trở lại năng động. tôi đoán nó sẽ ném ngoại lệ nếu loại không phải là một nhiệm vụ. Edit: tôi đã thử nghiệm nó. nó sẽ ném ngoại lệ nếu động không phải là Nhiệm vụ hoặc Nhiệm vụ . –

+6

Bạn có thể gọi 'GetAwaiter() 'trên' dynamic', do đó, có nó awaitable. – PetSerAl

Trả lời

8

async-await tính năng của trình biên dịch phụ thuộc vào Duck Typing. Vì vậy, tất cả những gì có phương pháp GetAwaiter (hoặc dụ hoặc mở rộng phương pháp) trả về kiểu mà thực hiện giao diện INotifyCompletion và có các lĩnh vực sau:

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

có thể chờ đợi.

Bạn có thể gọi bất cứ điều gì bạn muốn vào loại động tại thời gian biên dịch (từ docs):

Tại thời gian biên dịch, một yếu tố được đánh máy như động được giả định để hỗ trợ bất kỳ hoạt động.

Đó là lý do trình biên dịch không hiển thị bất kỳ cảnh báo/lỗi lúc biên dịch, nhưng khi chạy bạn sẽ nhận được một ngoại lệ tương tự như sau:

RuntimeBinderException.

'<> f__AnonymousType0' không chứa một định nghĩa cho 'GetAwaiter'

Nếu bạn chỉ định một cách rõ ràng gõ trình biên dịch sẽ tìm kiếm các phương pháp GetAwaiter. Sau đó, nếu loại mạnh của bạn không chứa nó, bạn sẽ nhận được lỗi thời gian biên dịch.

Vì vậy, câu trả lời cho câu hỏi của bạn là thực sự đó là vì hành vi đặc biệt của dynamic.

Các vấn đề liên quan