Warum werden AsObservable und AsEnumerable anders implementiert?

8

Die Implementierung von Enumerable.AsEnumerable<T>(this IEnumerable<T> source) gibt einfach source zurück. % Co_de% gibt jedoch einen Observable.AsObservable<T>(this IObservable<T> source) zurück, der die Quelle abonniert und nicht einfach die Quelle zurückgibt.

Ich verstehe, dass diese Methoden wirklich nützlich sind, um die Monade innerhalb einer einzigen Abfrage zu ändern (ausgehend von IQueryable = & gt; IEnumerable). Warum unterscheiden sich die Implementierungen?

Die AnonymousObservable<T> -Version ist defensiver, da sie nicht auf einen bekannten Typ umgewandelt werden kann (wenn das Original als Observable implementiert wäre, könnten Sie es niemals als solches darstellen). Also, warum macht die Subject<T> Version nichts ähnliches? Wenn mein zugrunde liegender Typ ein Enumerable ist, aber als List<T> bis IEnumerable<T> verfügbar ist, ist es möglich, zu einem AsEnumerable zurückzukehren.

Bitte beachten Sie, dass es sich hierbei nicht um eine Frage handelt, wie List<T> verfügbar gemacht werden kann, ohne dass eine Umwandlung in das zugrundeliegende System möglich ist, sondern warum die Implementierungen zwischen IEnumerable<T> und Enumerable semantisch unterschiedlich sind.

    
RichK 26.03.2012, 14:22
quelle

2 Antworten

13

Ihre Frage wird von der Dokumentation beantwortet, die ich Ihnen empfehlen zu lesen, wenn Sie solche Fragen haben.

Der Zweck von AsEnumerable besteht darin, dem Compiler "anzudeuten, dass Sie die Verwendung von IQueryable beenden und die Behandlung als In-Memory-Collection beginnen".

Wie die Dokumentation lautet:

  

Die AsEnumerable<TSource>(IEnumerable<TSource>) -Methode hat keinen anderen Effekt, als den Quellentyp der Kompilierungszeit von einem Typ zu ändern, der IEnumerable<T> in IEnumerable<T> selbst implementiert. AsEnumerable<TSource>(IEnumerable<TSource>) kann verwendet werden, um zwischen Abfrageimplementierungen zu wählen, wenn eine Sequenz IEnumerable<T> implementiert, aber auch andere öffentliche Abfrageverfahren zur Verfügung stehen.

Wenn Sie die Implementierung einer zugrunde liegenden Sequenz ausblenden möchten, verwenden Sie sequence.Select(x=>x) oder ToList oder ToArray , wenn Sie nicht möchten, dass Sie eine veränderbare Sequenz erstellen.

Der Zweck von AsObservable besteht darin, die Implementierung der zugrunde liegenden Sammlung zu verbergen. Als die Dokumentation sagt:

  

Observable.AsObservable<TSource> ... Versteckt die Identität einer beobachtbaren Sequenz.

Da die beiden Methoden völlig unterschiedliche Zwecke haben, haben sie völlig unterschiedliche Implementierungen.

    
Eric Lippert 26.03.2012, 14:34
quelle
9

Sie haben Recht bezüglich der Beziehung zwischen AsEnumerable und AsObservable hinsichtlich des Umstiegs von Ausdrucksbaum-basierten Abfragen auf In-Memory-Abfragen.

Gleichzeitig wird eine Rx-Sequenz basierend auf einem Subjekt & lt; T & gt; ist sehr üblich, und wir brauchten eine Möglichkeit, sie zu verstecken (andernfalls könnte der Benutzer auf IObservable & lt; T & gt; und Elemente injizieren).

Vor langer Zeit in der Geschichte der Rx-Pre-Releases hatten wir eine separate Hide-Methode, die lediglich ein Select-Alias ​​(x = & gt; x) war. Wir haben es nie gemocht und beschlossen, einen Ort zu haben, an dem wir vom LINQ to Objects-Precision Mirrorring abgewichen sind und AsObservable die Rolle von Hide spielen ließen, auch basierend auf Benutzern, die glaubten, dass dies das war, was sie anfing.

Beachten Sie jedoch, dass wir eine Erweiterungsmethode namens AsObservable für IQbservable & lt; T & gt; auch. Das macht einfach was AsEnumerable auch tut: Es dient als Hinweis für den Compiler, den Ausdrucksbaum-basierten Abfragemodus zu vergessen und zu In-Memory-Abfragen zu wechseln.

    
Bart De Smet 25.04.2012 07:28
quelle