8

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

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

我是否遗漏了某些东西,或者这是否等同于现有的Enumerable.SelectMany(), 减号this

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

3 回答 3

2

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

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

IObservable<TResult> For<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, IObservable<TResult>> resultSelector)

与,

IObservable<TResult> SelectMany<TSource, TResult>(this IObservable<TSource> source, Func<TSource, IObservable<TResult>> selector)

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

IEnumerable<TResult> For<TSource, TResult>(**IObservable**<TSource> source, Func<TSource, IEnumerable<TResult>> resultSelector)

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

于 2010-10-06T21:34:33.933 回答
0

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

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

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

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

于 2010-10-06T17:45:24.357 回答
0

我的猜测是 SelectMany 动态遍历所有内容,而 Concat(在 For 中)在开始注册和迭代之前遍历其所有外部 IEnumerable 元素。

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

于 2011-02-05T15:27:29.400 回答