2012-03-01 21 views
5

Estoy tratando de entender mejor la palabra clave yield y creo que tengo una comprensión lo suficientemente decente de ella, así que realicé algunas pruebas sin embargo me sorprendieron los resultados.Entender la palabra clave yield y LINQ

Si funciono con el código de abajo me sale el siguiente resultado que muestra que se realiza un bucle en todo el rango no sólo hasta el número 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; 
      } 
     } 
    } 

Salida:

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

Si Ejecuto el siguiente código que muestra que solo llega a 4 y luego se detiene.

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; 
      } 
     } 
    } 

Salida:

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

supongo que no estoy understading algo, pero parece como si LINQ está haciendo lo contrario de lo que espero que haga? Pensé que LINQ también usaba el rendimiento y la ejecución diferida y esperaba que los resultados del segundo conjunto de códigos fueran los mismos para el primer conjunto de códigos.

+0

'Donde' filtra los resultados, no deja de devolver resultados cuando un elemento satisface el predicado. Por otro lado, su bucle 'foreach' manual se rompe cuando se cumple el predicado ... –

Respuesta

12

Utiliza la ejecución diferida. LINQ Where comprueba todos los elementos de la entrada enumerable, no se detiene cuando llega al primer elemento encontrado. Eso es lo que hace First.

Su primer ejemplo devolvería lo mismo que el segundo ejemplo si cambió Where a First, o si eliminó el break del segundo ejemplo.

2

Creo que tiene su lógica básica equivocada, no LINQ. Su primer ejemplo tiene que iterar en todo el rango, porque la condición donde tiene que encontrar todos los valores que son 4, no solo el primer valor, que es igual a 4.

Cuestiones relacionadas