Rx: EnumerableEx.For () против Enumerable.SelectMany () - PullRequest
7 голосов
/ 06 октября 2010

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)

Ответы [ 3 ]

1 голос
/ 07 октября 2010

Хороший вопрос. Они дают одинаковые результаты, но внутренние реализации совершенно разные.

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 ответ.

0 голосов
/ 05 февраля 2011

Я предполагаю, что SelectMany обходит все динамически, тогда как Concat (в For) обходит все свои внешние элементы IEnumerable, прежде чем начать регистрироваться и выполнять их итерацию.

Другими словами, Concat работает с фиксированным набором IEnumerable, даже если он получает их как IEnumerable.Поэтому в For весь набор IEnumerable создается еще до того, как будет возвращен первый TResult.В SelectMany вы мгновенно получаете TResult.

0 голосов
/ 06 октября 2010

Они похожи на эквивалентную функциональность для меня.SelectMany - это метод расширения для IEnumerable и .For написан как статический метод для EnumerableEx, поэтому они вызываются по-разному.

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

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

Я уверен, что есть конкретные причины для использования каждого из них.

...