Domanda

Sto aggiungendo un'interfaccia LINQ to alcuni oggetti personalizzati, ma il C # compilatore non riesce a inferenza di tipo . Tuttavia, posso scrivere la query equivalente utilizzando i metodi di estensione prime e inferenza di tipo riesce, quindi non sono sicuro di come il compilatore sta traducendo l'espressione di query in chiamate di metodo di estensione.

C'è una bandiera utensile o compilatore così posso vedere quello che il compilatore genera dalla mia espressione di query in modo da questo numero?

Questo codice è in un progetto open source, quindi posso fornire link alla fonte se questo è utile. Lievi variazioni del tipo firme dei metodi di estensione evitare questo errore di inferenza di tipo, ma queste varianti non hanno la semantica che sto cercando.

È stato utile?

Soluzione

Il tuo codice di query comprensione è:

from f1 in e1
from f2 in e2
from f3 in e3
select f3

Il tuo codice chiamata del metodo è il seguente:

e1
.SelectMany(f1 => e2)
.SelectMany(f2 => e3), (f2, f3) => f3))

La traduzione interrogazione procede come segue. In primo luogo abbiamo a che fare con i primi due da clausole:

from f1 in e1
from f2 in e2
from f3 in e3
select f3;

Questa è tradotto in

from x in ( e1 ) . SelectMany( f1 => e2 , ( f1 , f2 ) => new { f1 , f2 } )
from f3 in e3
select f3;

dove "X" è un identificatore trasparente. Poiché nessuno di E1, E2 o E3 consumare qualsiasi variabile intervallo, il fatto che questo è un identificatore trasparente è irrilevante; riscrittura nessun ulteriore deve essere fatto per gestire la semantica identificatore trasparenti.

Questo risultato viene poi trasformato in

( ( e1 ) . SelectMany( f1 => e2 , ( f1 , f2 ) => new { f1 , f2 } ) ) 
.SelectMany( x => e3 , ( x , f3 ) => f3 )

Possiamo eliminare alcune di queste parentesi:

e1 
.SelectMany( f1 => e2 , ( f1 , f2 ) => new { f1 , f2 } ) ) 
.SelectMany( x => e3 , ( x , f3 ) => f3 )

Chiaramente questo è piuttosto diversa dalla trasformazione sintattica che hai fatto manualmente, che, ricordo, è stato

e1
.SelectMany(f1 => e2)
.SelectMany(f2 => e3), (f2, f3) => f3))

Se si sostituisce nella E1, E2, E3 nella trasformazione attuale sintattica sopra, fa il conseguente tipo passa espressione inferenza?

Se non lo fa, allora la domanda è "perché no?" O c'è qualcosa di sbagliato con il codice, o qualcosa che non va con il tipo inferrer. Se c'è qualcosa che non va con il tipo inferrer, fatemelo sapere.

Se è così, allora la domanda è "cosa c'è di sbagliato con il pass trasformazione sintattica"? Se c'è qualcosa di sbagliato con il pass trasformazione sintattica, ancora una volta, me lo faccia sapere.

Grazie!

Altri suggerimenti

È possibile utilizzare riflettore e visualizzare il codice con le ottimizzazioni spenti.

Panoramica di Eric mi ha portato a capire come queste query vengono elaborate. Il problema era che stavo cercando di limitare i tipi di essere operati in modo che la traduzione query non piaceva.

from x in Foo.Bar()
...

Foo.Bar () doveva restituire un futuro e x doveva anche essere di tipo futuro, ma questo non funziona con traduzione query. Ho affrontato questo aggiungendo un altro livello di riferimento indiretto, fondamentalmente avvolgendo future a dire, un Async tipo, che potrebbe essere istanziata solo termine, cioè.

public sealed class Async<T> { internal T value; }
public static class Async
{
   public static Async<Future<T>> Begin<T>(Future<T> future) { ... }
}

Allora posso scrivere calcoli di query sui valori Async, quindi l'espressione diventa qualcosa di simile a:

from x in Async.Begin(Foo.Bar())
...

dove x è ora di tipo futuro e può forzare o rinviare a termine e promette arbitrariamente.

Grazie per i suggerimenti di tutti. Un traduttore espressione di query integrata in Visual Studio sarebbe bello se, nel caso qualcuno a MS sta leggendo questo. ; -)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top