2010-10-06 9 views
7

System.Interactive.dll zawiera For() metodę z następującym realizacji:Rx: EnumerableEx.For() vs Enumerable.SelectMany()

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

jestem brakuje czegoś lub jest to równoznaczne z istniejącym Enumerable.SelectMany(), minus this?

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

Odpowiedz

1

Dobre pytanie. Dają takie same wyniki, ale wewnętrzne implementacje są zupełnie inne.

EnumerableEx.For zostałby dodany do System.Interactive w celu zachowania dualności między IObservable i IEnumerables. Zauważ, że Observable.For i Observable.SelectMany są różne:

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

vs.,

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

Dlatego można się spodziewać, że EnumerableEx.For miałby ten podpis, aniżeli ten, który faktycznie ma :

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

Jednak oczywiście nie pobiera źródła IObservable. Być może tak miało być. Zadałbym twoje pytanie na forach Rx, żeby sprawdzić, czy zespół Rx ma odpowiedź.

+0

Zapytany na forach Rx: http://social.msdn.microsoft.com/Forums/en-US/rx/thread/48992ccb-d2dc-4de4-8525-d88ce8622554 – dahlbyk

+0

Potwierdzony przez Bart De Smeta na forum Rx . – dahlbyk

0

Wyglądają jak odpowiednik dla mnie. SelectMany jest metodą rozszerzenia na IEnumerable i .Dla jest napisany jako metoda statyczna na EnumerableEx, więc są one nazywane inaczej.

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

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

Jestem pewien, że istnieją konkretne powody używania każdego z nich.

0

Domyślam się, że SelectMany przemierza wszystko dynamicznie, podczas gdy Concat (w For) przechodzi przez wszystkie zewnętrzne elementy IEnumerable przed rozpoczęciem rejestracji i iteracji nad nimi.

Innymi słowy, Concat pracuje ze stałym zestawem IEnumerable, nawet jeśli otrzymuje je jako IEnumerable. Dlatego też w For, cały zestaw IEnumerable jest tworzony przed nawet zwróceniem pierwszego TResultu. W SelectMany natychmiast otrzymujesz TRESULT.

+0

Ponieważ wszystkie zaangażowane podmioty (SelectMany, Select i Concat) są odłożone, nie jestem pewien, czy jakakolwiek różnica w implementacji przełożyłaby się na inne zachowanie końca. Niektóre testy z efektami ubocznymi w różnych punktach w selektorze każdego operatora wydają się zawsze dawać taki sam odroczony wynik. – dahlbyk

+0

W concat, już wiesz, ile IEnumerable musisz pracować, podczas gdy w SelectMany jego ilość zależy od tego, ile elementów przybyło ze źródła. W przypadku stałych źródeł wejściowych oba powinny wytwarzać to samo – akarnokd

Powiązane problemy