2015-10-09 15 views
6

Stavo usando Dapper e averlo restituire un IEnumerable dinamica, in questo modo:Perché First() o ElementAt() su un oggetto IEnumerable dinamico è attendibile?

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

Qui, rows è di tipo IEnumerable<dynamic>. IntelliSense dice che FirstOrDefault() è attendibile e ha l'utilizzo di await FirstOrDefault(). Non tutte le query LINQ vengono mostrate come attendibili, ma sembrano soprattutto quelle che in qualche modo individuano gli elementi.

Non appena utilizzo invece una digitazione forte, questo comportamento scompare.

È perché .NET non può sapere se il tipo che si sta ricevendo in fase di esecuzione è attendibile o meno, in modo che "lo consenta", nel caso sia necessario? Ma non lo applica? O dovrei, a causa di alcuni comportamenti di Dynamic Language Runtime, utilizzare effettivamente await qui?

Ho continuato a cercare ma non ho trovato la cosa più piccola di questo in linea.

+0

è possibile attendere dal ritorno dinamico. Immagino che genererà un'eccezione se type non è un Task. Modifica: l'ho provato genererà un'eccezione se la dinamica non è Task o Task . –

+6

Puoi chiamare 'GetAwaiter()' su 'dynamic', quindi sì è attendibile. – PetSerAl

risposta

8

async-await la funzione del compilatore dipende da Duck Typing. Quindi, tutto ciò che ha il metodo GetAwaiter (entrambi i casi o estensione metodo) che restituisce tipo che implementa l'interfaccia INotifyCompletion e ha i campi seguenti:

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

può essere atteso.

Si può chiamare quello che vuoi sul tipo dinamico in fase di compilazione (da docs):

In fase di compilazione, un elemento che viene digitato così dinamico si presume per supportare qualsiasi operazione.

Ecco perché il compilatore non mostra alcun avvertenze/errori in fase di compilazione, ma in fase di esecuzione si otterrà un'eccezione simile al seguente:

RuntimeBinderException.

'<> f__AnonymousType0' non contiene una definizione per 'GetAwaiter'

Se si specifica il tipo esplicitamente compilatore cercherà metodo GetAwaiter. Quindi se il tuo tipo forte non lo contiene, otterrai un errore in fase di compilazione.

Quindi, la risposta alla tua domanda è che, in effetti, è a causa del comportamento speciale di dynamic.