Ric*_*chK 9 c# linq ienumerable system.reactive
执行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>,但因为它暴露IEnumerable<T>通过AsEnumerable,将有可能投回List<T>.
请注意,这不是关于如何暴露出的问题IEnumerable<T>而不能够施展到底层,但为什么之间的实现Enumerable和Observable在语义上是不同的.
Eri*_*ert 16
您的问题由文档回答,我建议您在提出此类问题时阅读.
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
对于从基于表达式的查询切换到内存中查询的方面,AsEnumerable和AsObservable之间的关系是正确的.
同时,基于Subject <T>暴露Rx序列是非常常见的,我们需要一种方法来隐藏它(否则用户可以转换为IObservable <T>并注入元素).
很久以前在Rx预发布的历史中,我们确实有一个单独的Hide方法,它只是一个Select(x => x)别名.我们从来都不喜欢它,并决定有一个我们偏离LINQ to Objects精确镜像的地方,并使AsObservable扮演Hide的角色,同样基于那些认为这就是它开始的用户.
请注意,我们在IQbservable <T>上也有一个名为AsObservable的扩展方法.那个简单地完成了AsEnumerable所做的事情:它充当了编译器的提示,忘记了基于表达式的查询模式并切换到内存中查询.