Rx:EnumerableEx.For()vs Enumerable.SelectMany()

System.Interactive.dll包含一个For()方法,具有以下实现:

 IEnumerable For( IEnumerable source, Func<TSource, IEnumerable> resultSelector) { return source.Select<TSource, IEnumerable>(resultSelector).Concat(); } 

我错过了什么或者这相当于现有的Enumerable.SelectMany() ,减去this

 IEnumerable SelectMany( this IEnumerable source, Func<TSource, IEnumerable> selector) 

好问题。 它们产生相同的结果,但内部实现完全不同。

EnumerableEx.For将被添加到System.Interactive中以维护IObservable和IEnumerables之间的对偶性。 请注意,Observable.For和Observable.SelectMany是不同的:

 IObservable For(IEnumerable source, Func> resultSelector) 

对,

 IObservable SelectMany(this IObservable source, Func> selector) 

因此,您希望EnumerableEx.For具有此签名,而不是它实际拥有的签名:

 IEnumerable For(**IObservable** source, Func> resultSelector) 

但是,它显然不需要IObservable源。 也许它的意思是。 我会在Rx论坛上问你的问题,看看Rx团队是否有答案。

它们看起来像我的等效function。 SelectMany是IEnumerable上的扩展方法,而.For在EnumerableEx上作为静态方法编写,因此它们的调用方式不同。

  foreach(var s in list.SelectMany(Filter)) { // ... } foreach (var s in EnumerableEx.For(list, Filter)) { // ... } 

我确定使用每一个都有特定的原因。

我的猜测是SelectMany动态遍历所有内容,而Concat(在For中)遍历所有外部IEnumerable元素,然后开始注册并迭代它们。

换句话说,Concat使用一组固定的IEnumerable,即使它将它们作为IEnumerable接收它们。 因此,在For中,甚至在返回第一个TResult之前创建了整个IEnumerable集。 在SelectMany中,您会立即收到一个TResult。