2009-05-05 15 views
5

Dopo aver risposto this question ho messo insieme il seguente codice C# solo per divertimento:Infinite IEnumerable in un ciclo foreach

public static IEnumerable<int> FibonacciTo(int max) 
{  
    int m1 = 0; 
    int m2 = 1; 
    int r = 1; 

    while (r <= max) 
    { 
     yield return r; 

     r = m1 + m2; 
     m1 = m2; 
     m2 = r; 
    } 
} 

foreach (int i in FibonacciTo(56).Where(n => n >= 24)) 
{ 
    Console.WriteLine(i); 
} 

Il problema è che non mi piace dover passare un parametro max alla funzione. In questo momento, se non lo uso, il codice produrrà i dati corretti ma sembrerà bloccarsi mentre IEnumerable continua a funzionare. Come faccio a scrivere questo in modo che ho potuto solo usare in questo modo:

foreach (int i in Fibonacci().Where(n => n >= 24 && n <= 56)) 
{ 
    Console.WriteLine(i); 
} 

risposta

12

È necessario utilizzare una combinazione di SkipWhile e TakeWhile.

foreach (int i in Fibonacci().SkipWhile(n => n < 24) 
          .TakeWhile(n => n <= 56)) 
{ 
    Console.WriteLine(i); 
} 

Questi sono in grado di terminare i loop in base a una condizione; Where invia il proprio input (filtraggio in modo appropriato) finché l'input non si esaurisce (nel tuo caso, mai).

+0

L'avevo appena capito e stavo per pubblicarlo da solo. Strano come alla fine scrivere la domanda a volte punti all'ovvio –

+0

Hmm ... il mio problema di base è che mi sono fissato per farlo in una sola espressione lambda. Ora sono tentato di scrivere anche una nuova estensione "IgnorotenTakeWhile()" IEnumerable che permetterebbe questo, se solo potessi pensare ad un nome migliore per questo;) –

+0

Mentre mi piace scrivere anche gli operatori LINQ, mi chiederei se questo sembra davvero abbastanza spesso per meritarne uno;) –

-2

non credo che questo è possibile a meno che non si scrive il proprio fornitore di LINQ. Nell'esempio che hai dato stai usando LINQ to Objects che dovrà valutare completamente l'IEnumerable prima di poter applicare un filtro ad esso.

+4

Fortunatamente IEnumerable non funziona in questo modo: applica il filtro mentre valuta in modo che i dati vengano trasmessi in streaming anziché ripetuti. –

+0

Joel sei corretto, ho dimenticato i miei principi di base della programmazione funzionale in cui un'operazione non può avere un effetto collaterale. –