2010-12-14 14 views
13

Desde ForEach() bucle método a través de todos unos miembros de la lista, ¿Por qué no puede usar un descanso /continuar cláusula mientras pueda utilizarlos dentro de un bucle foreach normalesForEach(): ¿Por qué no se puede utilizar pausa/continuar dentro

lstTemp.ForEach(i=> 
{ 
    if (i == 3) 
    break; 
    //do sth 
} 
); 

error:

"No enclosing loop out of which to break or continue"

+0

Una extensión ParaCada bien escrita debería permitir que devuelva false si desea que se rompa. Pero no puedo asegurarlo ya que no sé de dónde sacaste tu foreach. Si lo escribió usted mismo, puede ser una buena opción. – Tesserex

+0

Parece que desea la función TakeWhile http://msdn.microsoft.com/en-us/library/bb534804%28v=VS.90%29.aspx – Juliet

+0

Encontré una mejor respuesta aquí: http://stackoverflow.com/questions/3145563/list-foreach-break –

Respuesta

18

Porque ForEach es un método y no un bucle foreach normal. El método ForEach está ahí para tareas simples, si necesita interrumpir o continuar solo iterar sobre lstTemp con un bucle normal foreach.

Por lo general, ForEach se implementa como esto:

public static ForEach<T>(this IEnumerable<T> input, Action<T> action) 
{ 
    foreach(var i in input) 
    action(i); 
} 

Como se trata de una llamada a un método normal, action no se sabe nada sobre el foreach que encierra, por lo tanto no se puede romper.

+0

Dado que se trata de una llamada a un método, ¿puedo simplemente devolver en lugar de romper? – Lance

+0

No, solo volverá del método en sí. No podrás salir de un foreach externo de esa manera. – Femaref

17

Presumiblemente porque estás utilizando un lambda y el contenido de la lambda es ignorante al hecho de que se está utilizando dentro de un bucle.

2

break y continue son palabras clave de lenguaje C# que requieren compatibilidad con el compilador. ForEach, para el compilador de C#, es solo un método.

4

La forma en que lo explicaría es la siguiente: ForEach es un método , no es una característica idioma. El constructo C# foreach es una característica del lenguaje en el que están permitidos los otros constructos de lenguaje break y continue.

También señalaría (no tratando de juzgar, simplemente haciendo una observación) que este es un buen ejemplo de por qué algunos desarrolladores objetan el uso de un método ForEach: realmente no ahorra escribir en este simple caso , requiere una redirección más de lo necesario, y no tiene toda la funcionalidad de foreach de todos modos.

En mi opinión, el escenario principal en el que tiene sentido un método ForEach es como una extensión en IEnumerable<T> - para poner al final de una cadena de llamadas a métodos. Me parece (a mí) un poco extraño que lo hayan agregado al List<T>.

0

Porque delega una acción para cada elemento en la lista.

10

en lugar de utilizar un descanso, realizar un primer filtro como esta (que puede no ser el filtro exacto que necesita, pero ilustra el punto)

lstTemp.Where(i => i!= 3).ForEach(i=> // do sth); 
+0

-1 No es lo mismo. su código se ejecutará para cada i! = 3. El código presentado se ejecutará hasta que i == 3. – Sergio

+0

Esta parece ser la mejor manera para 'continuar'. Además, podemos escribir 'return' para 'break'. – Nigiri

0

puede escribir un método de extensión "ForEachWhile" que se lleva a Function<T, bool> y se detiene cuando es falso.

5

para recorrer sólo una parte de los artículos y emular la ruptura perfectamente, puede utilizar FirstOrDefault:

lstTemp.FirstOrDefault(i=> 
{ 
    if (i == 3) 
     return true; 

    //do stuff 

    return false; 
} 
); 

Para la lista con 100.000 artículos, si el 10 Articulo 3 que se repetirá sólo 10 veces, utilizando el Where solución funcionará, pero itere toda la lista primero.

+1

El método 'Where' no itera la colección, ver: ejecución diferida. –

+0

@James quizás * iterar * no es la palabra correcta ... pero para encontrar todos los elementos coincidentes, en algún lugar, de alguna manera, todos los elementos deben ser revisados, ¿no es así? –

+1

Lea cómo funciona la palabra clave 'yield', porque así es como funcionan las consultas LINQ. Es demasiado largo para explicarlo aquí, pero no, no todos los artículos deben ser revisados; solo se verificarán tantos elementos solicitados por la cadena de llamadas. Exactamente igual que su 'FirstOrDefault', que se repetirá hasta que golpee una coincidencia. –

-1

lo utilicé

 list.ForEach((item) => 
     { 
      if(isBreak == false) do 
      { 
       if (isContinue) 
        break; 

       // TODO 
      } while (false); } 
     }); 
+0

esto no responde exactamente la pregunta. OP pregunta por qué él/ella no puede usar break/continue como un bucle normal. – Rafael

+0

Intenta eliminar el 'do-while' y utiliza' break', LOL. – code4life

3

return actuará como continue en ForEach.

Ejemplo:

var list = new List<int>() {1, 2, 3, 4}; 
list.ForEach(i => 
    { 
     if (i == 3) 
      return; 
     Console.WriteLine(i); 
    } 
); 

Prints 1, 2, 4.

3 - saltado.

1

Dado que ForEach es un método y no un bucle foreach regular, es necesario iterar sobre lstTemp con un bucle foreach normal en caso de salto, pero en caso de continuar, vuelva a utilizar el método ForEach.

var lstTemp = new List<int>() {1, 2, 3, 4}; 
lstTemp.ForEach(i=> 
{ 
    if (i == 3) return; 
    //do sth 
    Console.WriteLine(i); 
}); 

de salida: 1, 2, 4

Cuestiones relacionadas