Почему AsObservable и AsEnumerable реализованы по-разному? - PullRequest
9 голосов
/ 26 марта 2012

Реализация Enumerable.AsEnumerable<T>(this IEnumerable<T> source) просто возвращает source.Однако Observable.AsObservable<T>(this IObservable<T> source) возвращает AnonymousObservable<T> подписку на источник, а не просто возврат источника.

Я понимаю, что эти методы действительно полезны для изменения монады в пределах одного запроса (исходя из IQueryable => IEnumerable).Так почему же реализации различаются?

Версия Observable является более защитной, в том смысле, что вы не можете привести ее к какому-либо известному типу (если бы она изначально была реализована как Subject<T>, вы бы никогда не былив состоянии бросить его как таковой).Так почему же версия Enumerable не делает ничего подобного?Если моим базовым типом является List<T>, но его можно выставить как IEnumerable<T> - AsEnumerable, можно будет вернуться к List<T>.

Обратите внимание, что это не вопрос окак выставить IEnumerable<T> без возможности приведения к базовому объекту, но почему реализации между Enumerable и Observable семантически отличаются.

Ответы [ 2 ]

16 голосов
/ 26 марта 2012

На ваш вопрос отвечает документация, которую я рекомендую вам прочитать, когда у вас есть такие вопросы.

Цель AsEnumerable - дать указание компилятору «пожалуйста, прекратите использование IQueryable и начните обрабатывать это как коллекцию в памяти».

Как документация гласит:

Метод AsEnumerable<TSource>(IEnumerable<TSource>) не имеет никакого другого эффекта, кроме как изменить тип источника времени компиляции с типа, который реализует IEnumerable<T> на IEnumerable<T>. AsEnumerable<TSource>(IEnumerable<TSource>) может использоваться для выбора между реализациями запросов, когда последовательность реализует IEnumerable<T>, но также имеет другой набор доступных методов запросов.

Если вы хотите скрыть реализацию базовой последовательности, используйте sequence.Select(x=>x) или ToList или ToArray, если вам все равно, что вы создаете изменяемую последовательность.

Цель AsObservable - скрыть реализацию базовой коллекции. Как документация гласит:

Observable.AsObservable<TSource> ... Скрывает идентичность наблюдаемой последовательности.

Поскольку эти два метода имеют совершенно разные цели, они имеют совершенно разные реализации.

10 голосов
/ 25 апреля 2012

Вы правы относительно отношений между AsEnumerable и AsObservable в аспекте перехода от запросов на основе дерева выражений к запросам в памяти.

В то же время раскрытие последовательности Rx на основе субъекта очень распространено, и нам нужен был способ скрыть это (в противном случае пользователь мог бы привести к IObservable и добавить элементы).

Давным-давно в истории предварительных выпусков Rx у нас был отдельный метод Hide, который был просто псевдонимом Select (x => x). Нам это никогда не нравилось, и мы решили иметь место, где мы отклонились от точного зеркального отображения LINQ to Objects, и заставили AsObservable играть роль Hide, также основываясь на пользователях, которые полагали, что именно это и было с самого начала.

Обратите внимание, что у нас есть метод расширения AsObservable для IQbservable . Тот просто делает то же, что и AsEnumerable: он служит подсказкой компилятору забыть о режиме запросов на основе дерева выражений и переключиться на запросы в памяти.

...