2010-10-06 11 views
7

System.Interactive.dll include un metodo For() con la seguente implementazione: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>(); 
} 

Mi manca qualcosa o è equivalente a quella esistente Enumerable.SelectMany(), meno this?

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

risposta

1

Buona domanda. Producono gli stessi risultati ma le implementazioni interne sono abbastanza diverse.

EnumerableEx.For sarebbe stato aggiunto a System.Interactive per mantenere la dualità tra IObservable e IEnumerables. Si noti che Observable.For e Observable.SelectMany sono diversi:

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

contro,

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

Pertanto ci si aspetterebbe che EnumerableEx.For avrebbe avuto questa firma, piuttosto che quello che ha in realtà :

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

Tuttavia, ovviamente non utilizza una sorgente IObservable. Forse era destinato a. Vorrei fare la tua domanda nei forum Rx, per vedere se il team Rx ha una risposta.

+0

Alla domanda sui forum Rx: http://social.msdn.microsoft.com/Forums/en-US/rx/thread/48992ccb-d2dc-4de4-8525-d88ce8622554 – dahlbyk

+0

Confermato da Bart De Smet sul forum Rx . – dahlbyk

0

Sembrano simili funzionalità equivalenti. SelectMany è un metodo di estensione su un oggetto IEnumerable e .For è scritto come metodo statico su EnumerableEx, quindi vengono chiamati in modo diverso.

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

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

Sono sicuro che ci sono motivi specifici per l'utilizzo di ciascuno.

0

La mia ipotesi è che SelectMany attraversa tutto dinamicamente, mentre Concat (in For) attraversa tutti gli elementi IEnumerable esterni prima di iniziare a registrarsi e scorrere su di essi.

In altre parole, Concat funziona con un set fisso di IEnumerable anche se li riceve come IEnumerable. Pertanto, in For, viene creato l'intero set di IEnumerable prima ancora di restituire il primo TResult. In SelectMany, ricevi un TResult all'istante.

+0

Dato che tutti gli operatori coinvolti (SelectMany, Select e Concat) sono differiti, non sono sicuro che eventuali differenze nell'implementazione si tradurranno in un comportamento diverso. Alcuni test con effetti collaterali in vari punti nel selettore di ciascun operatore sembrano sempre produrre lo stesso risultato differito. – dahlbyk

+0

In concat, sai già quanti IEnumerable devi lavorare, mentre in SelectMany, la sua quantità dipende da quanti elementi arrivano dalla sorgente. Per fonti di input di dimensioni costanti, entrambe dovrebbero produrre lo stesso – akarnokd