2011-11-16 13 views
9

Duplicar posible:
Breaking out of a nested loop¿Doble salto de foreach con una instrucción "If"?

Tengo algo como (para simplificar)

foreach (...) 
{ 
    foreach (...) 
    { 
     //Some code 

     if (statement) 
     { 
      break; 
     } 
    } 
} 

Lo que pasa es que quiero que mi declaración a dejar para el doble foreach lazo ! Estoy pensando en una especie de "bandera de ruptura" como booleano, pero ¿hay alguna forma de evitar eso?

+0

se puede evitar mediante el uso de '' Linq' y SelectMany' para hacer esto una sola fines de cada bucle en lugar de un bucle anidado . –

+1

"romper bandera" o GOTO – relaxxx

+0

@Merlyn Morgan-Graham: ¡no sé nada al respecto, échele un vistazo! –

Respuesta

7

Puede evitar el ciclo anidado utilizando Linq y SelectMany.

En lugar de:

foreach(var value in someValues) 
{ 
    foreach(var subValue in value.SubValues) 
    { 
     // ... 
     break; 
    } 
} 

Su código se convertiría en:

foreach(var subValue in someValues.SelectMany(v => v.SubValues)) 
{ 
    // ... 
    break; 
} 

Si necesita algo de lógica para seleccionar si desea que se recorre SubValues, lanzar esa lógica en una cláusula adicional Where.

En lugar de

foreach(var value in someValues) 
{ 
    if(value.IsMumsHairGreenToday) 
    { 
     foreach(var subValue in value.SubValues) 
     { 
      // ... 
      break; 
     } 
    } 
} 

Se puede escribir:

var subValues = someValues 
    .Where(v => v.IsMumsHairGreenToday) 
    .SelectMany(v => v.SubValues) 
    ; 

foreach(var subValue in subValues) 
{ 
    // ... 
    break; 
} 
+0

No estoy cómodo con expresiones lambda, así que no pensé en hacer esto, suena bien, evito el desayuno y uso un GOTO! –

+3

@GuillaumeCogranne: Nunca se sentirá cómodo hasta que los use todo el tiempo. Por cierto, por favor, nunca uses 'goto'. No me importa lo que diga la multitud. Es simplemente pecaminoso :) –

1

se podría encapsular esa lógica en un método y volver al punto de ruptura:

private SomeType CheckIfConditionOfNestedItems(IEnumerable enumerable) 
{ 
    foreach (var thing in enumerable) 
    { 
     foreach (...) 
     { 
      //Some code 

      if (statement) 
      { 
       return result; 
      } 
     } 
    } 
} 

, obviamente, esto puede que tenga que cambiar su código un poco, pero esto también tiene la ventaja de que es probable que tenga el código donde tienes el doble bucle mucho más legible.

+0

no encaja bien con mi código -_- –

7

Usted podría intentar:

bool leave = false; 
foreach (...) 
{ 
    foreach (...) 
    { 
     //Some code 

     if (statement) 
     { 
      leave = true; 
      break; 
     } 
    } 
    if (leave) break; 
} 

edición: trasladó la bandera ruptura

+1

sí, ese es el "desayuno" del que estaba hablando pero no me gusta -_- –

+0

@GuillaumeCogranne: ops, no lo leí ... – Marco

10

Es posible utilizar goto.

+0

¿Estás bromeando? – sll

+0

goto FTW :) yay – jgauffin

+0

Sin usar un descanso flag, goto es prácticamente la única opción para saltar desde múltiples bucles anidados. – Tudor

5

Claro, deberías marcar goto.

+0

¿Puede algún infractor explicar por qué lo hizo? – DanielB

+1

¿Quién y por qué rechazó eso? ¿Solo porque su "lógica" común que goto es malvada? ¡No! ¡No es! Todavía está en el idioma por una razón y a veces, aunque raro, estoy de acuerdo, es útil. – dowhilefor

+2

no estoy de acuerdo con el -2 aquí - él tiene un punto válido :) –

2

Como break solo se rompe el bucle de corriente, también tendrá que probar la condición de corte en el bucle externo, a menos que use una instrucción goto.

Una variable parece ser la mejor manera de hacerlo.

2

Imo uno de los pocos casos en que un cuidadoso goto está bien.

Cuestiones relacionadas