2012-03-26 14 views
8

L'implementazione di Enumerable.AsEnumerable<T>(this IEnumerable<T> source) restituisce semplicemente source. Tuttavia, Observable.AsObservable<T>(this IObservable<T> source) restituisce un AnonymousObservable<T> abbonandosi all'origine piuttosto che semplicemente restituendo la fonte.Perché AsObservable e AsEnumerable sono implementati in modo diverso?

Capisco che questi metodi siano davvero utili per modificare la monade all'interno di una singola query (passando da IQueryable => IEnumerable). Quindi perché le implementazioni differiscono?

La versione Observable è più difensiva, nel senso che non puoi lanciare a qualche tipo noto (se originale sono state attuate come Subject<T> si sarebbe mai in grado di lanciare come tale). Allora perché la versione Enumerable non fa qualcosa di simile? Se il mio tipo sottostante è List<T> ma lo esponi come IEnumerable<T> tramite AsEnumerable, sarà possibile eseguire il cast di nuovo su List<T>.

Si prega di notare che questa non è una domanda su come esporre IEnumerable<T> senza essere in grado di lanciare al sottostante, ma perché le implementazioni tra Enumerable e Observable sono semanticamente differenti.

risposta

13

La tua domanda ha una risposta dalla documentazione, che ti incoraggio a leggere quando hai domande del genere.

Lo scopo di AsEnumerable è di suggerire al compilatore "interrompere l'utilizzo di IQueryable e iniziare a considerarlo come una raccolta in memoria".

Come the documentation stati:

Procedimento AsEnumerable<TSource>(IEnumerable<TSource>) ha alcun effetto se non per cambiare la fase di compilazione di origine da un tipo che implementa IEnumerable<T> a IEnumerable<T> stessa. AsEnumerable<TSource>(IEnumerable<TSource>) può essere utilizzato per scegliere tra le implementazioni di query quando una sequenza implementa IEnumerable<T> ma dispone anche di un diverso insieme di metodi di query pubblici disponibili.

Se si desidera nascondere l'implementazione di una sequenza sottostante, utilizzare sequence.Select(x=>x) o ToList o ToArray se non si cura che si sta facendo una sequenza mutabile.

Lo scopo di AsObservable è nascondere l'implementazione della raccolta sottostante. Come the documentation dice:

Observable.AsObservable<TSource> ... Nasconde l'identità di una sequenza osservabile.

Poiché i due metodi hanno scopi completamente diversi, hanno implementazioni completamente diverse.

+0

Grazie per la spiegazione. Di recente ho visto un video su Channel 9 con Bart De Smet in cui spiegava IQbservable e la sua relazione con IObservable. Dal modo in cui l'ha spiegato, sembrava che AsObservable fosse l'analogo di AsEnumerable in quanto qualsiasi azione osservabile sarebbe avvenuta localmente piuttosto che remotamente. Ho completamente frainteso questo (probabilmente ...), o è semplicemente un altro uso di AsObservable? – RichK

+0

Non lo so. Consiglio di porre questa domanda a Bart de Smet. –

+0

Ok, grazie, probabilmente una buona idea. Ho letto la documentazione prima di chiedere - ma la confusione era il risultato del video menzionato nel mio precedente commento – RichK

9

Hai ragione circa la relazione tra AsEnumerable e AsObservable rispetto all'aspetto del passaggio da query basate su albero di espressioni a query in memoria.

Allo stesso tempo, esponendo una sequenza Rx basata su un soggetto <T> è molto comune, e abbiamo bisogno di un modo per nascondere (altrimenti l'utente potrebbe cast IObservable <T> e iniettare elementi).

Tanto tempo fa nella storia della Rx pre-release, abbiamo avuto un metodo Nascondi separato, che era solo a Selezionare (x = > x) alias. Non ci è mai piaciuto e abbiamo deciso di creare un luogo in cui abbiamo deviato il LINQ in modo speculare agli oggetti, e ho reso AsObservable il ruolo di Hide, anche in base agli utenti che credevano che questo fosse ciò che ha fatto per cominciare.

Avviso, tuttavia, abbiamo un metodo di estensione denominato AsObservable su IQbservable <T>. Questo fa semplicemente ciò che fa AsEnumerable: agisce come suggerimento per il compilatore per dimenticare la modalità di query basata su espressioni e passare alle query in memoria.

+0

Grazie per aver verificato questa vecchia domanda, Bart, la tua risposta fornisce alcune informazioni interessanti. – RichK