为什么AsObservable和AsEnumerable的实现不同?
Enumerable.AsEnumerable<T>(this IEnumerable<T> source)
只是返回source
。 然而, Observable.AsObservable<T>(this IObservable<T> source)
返回一个订阅源的AnonymousObservable<T>
,而不是简单地返回源。
我知道这些方法对于在单个查询中更改monad非常有用(从IQueryable => IEnumerable)。 那么为什么这些实现有所不同?
Observable
版本更具防御性,因为你不能将它转换成某种已知类型(如果它原来是作为Subject<T>
实现的,你永远无法将它转换为此类)。 那么为什么Enumerable
版本不能做类似的事情呢? 如果我的基础类型是一个List<T>
但通过AsEnumerable
将其暴露为IEnumerable<T>
,则可以将其转换回List<T>
。
请注意,这不是一个关于如何暴露IEnumerable<T>
而不能转换为底层的问题,但为什么Enumerable
和Observable
之间的实现在语义上是不同的。
您的问题由文档回答,我鼓励您在遇到此类问题时阅读。
AsEnumerable的目的是向编译器提示“请停止使用IQueryable并开始将其视为内存中的集合”。
正如文档所述:
除了将编译时类型的源从实现IEnumerable<T>
的类型更改为IEnumerable<T>
本身之外, AsEnumerable<TSource>(IEnumerable<TSource>)
方法无效。 当序列实现IEnumerable<T>
时, AsEnumerable<TSource>(IEnumerable<TSource>)
可用于在查询实现之间进行选择,但也可以使用不同的公共查询方法。
如果你想隐藏一个底层序列的实现,使用sequence.Select(x=>x)
或ToList
或ToArray
如果你不关心你正在做一个可变序列。
AsObservable的目的是隐藏底层集合的实现。 正如文件所述:
Observable.AsObservable<TSource>
...隐藏可观察序列的标识。
由于这两种方法有完全不同的用途,它们具有完全不同的实现。
关于AsEnumerable和AsObservable之间的关系,从基于表达式树的查询切换到内存查询,您是对的。
同时,基于Subject <T>公开一个Rx序列是非常常见的,我们需要一种方法来隐藏它(否则用户可以投射到IObservable <T>并注入元素)。
很久以前,在Rx预发布的历史中,我们确实有一个单独的Hide方法,它只是一个Select(x => x)别名。 我们从来不喜欢它,并决定让我们偏离LINQ到Objects的精确镜像,并使AsObservable扮演Hide角色,也是基于那些认为这就是它开始的用户的基础。
但是请注意,我们在IQbservable <T>上也有一个名为AsObservable的扩展方法。 那个人简直就是AsEnumerable所做的:它作为编译器的提示,忘记基于表达式树的查询模式并切换到内存查询。
链接地址: http://www.djcxy.com/p/85057.html上一篇: Why Are AsObservable and AsEnumerable Implemented Differently?