2012-03-26 47 views
8

执行Enumerable.AsEnumerable<T>(this IEnumerable<T> source)只需返回source。但Observable.AsObservable<T>(this IObservable<T> source)返回订阅源的AnonymousObservable<T>,而不是简单地返回源。为什么AsObservable和AsEnumerable的实现不同?

我知道这些方法对于在单个查询(从IQueryable => IEnumerable)中更改monad非常有用。那么为什么这些实现有所不同?

Observable版本更具防御性,因为您无法将其转换为某种已知类型(如果原始版本实施为Subject<T>,您将无法将其转换为此类版本)。那么为什么Enumerable版本不做类似的事情?如果我的基础类型是List<T>,但将其公开为IEnumerable<T>AsEnumerable,则可以将其重新转换为List<T>

请注意,这不是关于如何暴露IEnumerable<T>而不能转换为底层的一个问题,但为什么EnumerableObservable之间的实现在语义上的不同。

回答

13

您的问题由文档回答,我鼓励您在遇到此类问题时阅读。

AsEnumerable的目的是向编译器暗示“请停止使用IQueryable并开始将其作为内存中的集合”。

作为the documentation状态:

AsEnumerable<TSource>(IEnumerable<TSource>)方法以外的其他来源的编译时间类型从实现IEnumerable<T>IEnumerable<T>本身类型改变没有任何影响。 AsEnumerable<TSource>(IEnumerable<TSource>)可用于在序列实现IEnumerable<T>时的查询实现之间进行选择,但也可使用不同的公共查询方法。

如果要隐藏底层的执行顺序,使用sequence.Select(x=>x)ToListToArray,如果你不关心你正在做一个可变的序列。

AsObservable的目的是隐藏底层集合的实现。正如the documentation所说:

Observable.AsObservable<TSource> ...隐藏可观察序列的身份。

由于两种方法有完全不同的用途,它们有完全不同的目的。

+0

感谢您的解释。我最近在Bart De Smet的Channel 9上观看了一段视频,他解释了IQbservable,它与IObservable有关系。从他解释的方式来看,它听起来像AsObservable是AsEnumerable的模拟,因为任何可观察的行为都会在本地发生,而不是远程发生。我完全误解了这个(可能是......),还是仅仅是AsObservable的另一个用法? – RichK 2012-03-26 14:42:57

+0

我不知道。我建议问巴特德斯梅特那个问题。 – 2012-03-26 14:44:29

+0

好的,谢谢,可能是一个好主意。在提问之前,我确实阅读了文档 - 但是由于我之前的评论中提到的视频导致了混淆 – RichK 2012-03-26 14:48:04

9

对于AsEnumerable和AsObservable之间的关系以及从基于表达式树的查询切换到内存查询的方面,你是正确的。

与此同时,露出基于对象<牛逼>的Rx序列是很常见的,我们需要一种方法来隐藏它(否则用户可以强制转换的IObservable <牛逼>并注入元素)。我们确实有一个单独的Hide方法,它只是一个Select(x = > x)别名。我们从来不喜欢它,并决定让我们偏离LINQ到Objects的精确镜像,并使AsObservable扮演Hide角色,也是基于那些认为这就是它开始的用户的基础。

但请注意,我们在IQbservable <T>上也有一个名为AsObservable的扩展方法。那个人简直就是AsEnumerable所做的:它作为编译器的提示,忘记基于表达式树的查询模式并切换到内存查询。

+0

感谢您检查这个老问题Bart,您的答案提供了一些有趣的信息。 – RichK 2012-04-25 09:18:38

相关问题