2012-03-01 18 views
5

Sto cercando di capire meglio la parola chiave yield e penso di averne una conoscenza abbastanza decente, quindi ho eseguito alcuni test, ma sono stato sorpreso dai risultati.Capire la parola chiave yield e LINQ

Se eseguo il codice qui sotto ottengo il seguente output che dimostra che loop su tutto il campo, non solo fino al numero 4.

public void DoIt() 
    { 
     Console.WriteLine("Method Call"); 
     var results = GetData(Enumerable.Range(1, 10)); 
     Console.WriteLine("LINQ"); 
     var filtered = results.Where(x => x == 4); 
     Console.WriteLine("Start result loop"); 
     foreach (var item in filtered) 
     { 
       Console.WriteLine("Item is " + item); 
     } 
    } 

    private IEnumerable<int> GetData(IEnumerable<int> Input) 
    { 
     foreach (int item in Input) 
     { 
      if (item % 2 == 0) 
      { 
       Console.WriteLine("Found " + item); 
       yield return item; 
      } 
     } 
    } 

uscita:

Method Call 
LINQ 
Start result loop 
Found 2 
Found 4 
Item is 4 
Found 6 
Found 8 
Found 10 

Se Corro il codice qui sotto mostra che arriva solo a 4 e poi si ferma.

public void DoIt() 
    { 
     Console.WriteLine("Method Call"); 
     var results = GetData(Enumerable.Range(1, 10)); 
     Console.WriteLine("Start result loop"); 
     foreach (var item in results) 
     { 
      if (item == 4) 
      { 
       Console.WriteLine("Item is " + item); 
       break; 
      } 
     } 
    } 

    private IEnumerable<int> GetData(IEnumerable<int> Input) 
    { 
     foreach (int item in Input) 
     { 
      if (item % 2 == 0) 
      { 
       Console.WriteLine("Found " + item); 
       yield return item; 
      } 
     } 
    } 

uscita:

Method Call 
Start result loop 
Found 2 
Found 4 
Item is 4 

Credo che non sto understading qualcosa, ma sembra come se LINQ sta facendo il contrario di quello che mi aspetto che faccia? Anche se LINQ ha utilizzato anche la resa e l'esecuzione posticipata e mi aspetto che i risultati del secondo set di codice siano gli stessi per il primo set di codice.

+0

'Where' filtra i risultati, non smette di restituire risultati quando un oggetto soddisfa il predicato. D'altra parte, il ciclo manuale 'foreach' si interrompe quando il predicato è soddisfatto ... –

risposta

12

Utilizza l'esecuzione differita. LINQ Where controlla tutti gli elementi di input enumerable, non si ferma quando arriva al primo elemento trovato. Questo è ciò che fa First.

Il primo esempio restituisce lo stesso del secondo esempio se è stato modificato Where in First o se è stato rimosso il break dal secondo esempio.

2

Penso che tu abbia sbagliato la tua logica di base, non LINQ. Il tuo primo esempio deve iterare su tutto l'intervallo, perché la condizione where deve trovare tutti i valori uguali a 4, non solo il primo valore, uguale a 4.

Problemi correlati