2010-12-14 4 views
13

Dal foreach() metodo di scorrere tutti un iscritti della lista, perché non posso usare una pausa /continuare clausola, mentre io li posso usare all'interno di un normale ciclo foreachforeach(): Perché non è possibile utilizzare pausa/continuare all'interno

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

Errore:

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

+0

Un'estensione PerOgni ben scritto dovrebbe consentire di restituire false se si vuole la rottura. Ma non posso dirlo con certezza dato che non so dove hai preso il tuo consiglio. Se l'hai scritto tu stesso, questa potrebbe essere una buona opzione. – Tesserex

+0

Sembra che si desideri la funzione TakeWhile http://msdn.microsoft.com/en-us/library/bb534804%28v=VS.90%29.aspx – Juliet

+0

Ho trovato una risposta migliore qui: http://stackoverflow.com/questions/3145563/list-foreach-break –

risposta

18

Perché ForEach è un metodo e non un ciclo regolare foreach. Il metodo ForEach è disponibile per attività semplici, se è necessario interrompere o continuare semplicemente iterare su lstTemp con un ciclo regolare foreach.

Di solito, ForEach è implementato in questo modo:

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

Poiché si tratta di un metodo normale chiamata, action non sa nulla della racchiudendo foreach, quindi non si può rompere.

+0

Dato che si tratta di una chiamata di metodo, posso semplicemente tornare invece di interrompere? – Lance

+0

No, tornerai dal metodo stesso. Non sarai in grado di uscire da un campo esterno in quel modo. – Femaref

17

Presumibilmente perché si sta utilizzando un lambda e il contenuto del lambda siete ignoranti al fatto che è in uso all'interno di un ciclo.

2

interruzione e continuazione sono parole chiave in linguaggio C# che richiedono il supporto del compilatore. ForEach, per il compilatore C#, è solo un metodo.

4

Il modo in cui mi piacerebbe spiegarlo è questo: ForEach è un metodo , non una caratteristica lingua. Il costrutto C# foreach è una funzionalità della lingua all'interno della quale sono costruite le altre lingue break e continue.

Vorrei anche sottolineare (non cercando di giudicare, solo facendo un'osservazione) che questo è un buon esempio del perché alcuni sviluppatori si oppongono all'uso di un metodo ForEach: in realtà non salva la digitazione in questo semplice caso , richiede un ulteriore reindirizzamento del necessario e non ha comunque tutte le funzionalità di foreach.

A mio parere lo scenario principale in cui un metodo ForEach ha senso è come un'estensione su IEnumerable<T> - da mettere alla fine di una catena di chiamate di metodo. Sembra (per me) un po 'strano che lo abbiano aggiunto a List<T>.

0

Poiché si delegano un'azione per ciascun elemento nell'elenco.

10

piuttosto che utilizzare una pausa, eseguire un filtro prima come questo (che non può essere il filtro esatto si ha bisogno, ma illustra il punto)

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

-1 Non il samething. il codice verrà eseguito per ogni i! = 3. Il codice presentato verrà eseguito fino a i == 3. – Sergio

+0

Questo sembra il modo migliore per 'continuare'. Inoltre possiamo semplicemente scrivere "return" per "break". – Nigiri

0

È possibile scrivere un metodo di estensione "ForEachWhile" che prende a Function<T, bool> e si ferma quando falso.

5

per iterare solo una parte degli elementi e emulare la pausa perfetta, è possibile utilizzare FirstOrDefault:

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

    //do stuff 

    return false; 
} 
); 

Per l'elenco con 100000 articoli, se il 10 ° elemento è 3 sarà iterare solo 10 volte, utilizzando il La soluzione Where funzionerà, ma itererà prima l'intera lista.

+1

Il metodo 'Where' non itera la collezione, vedi: esecuzione differita. –

+0

@James forse * iterate * non è la parola giusta .. ma per trovare tutti gli elementi corrispondenti, da qualche parte in qualche modo tutti gli elementi devono essere controllati, non è vero? –

+1

Leggi come funziona la parola chiave 'yield', perché è così che funzionano le query LINQ. È troppo lungo per spiegare qui, ma no, non tutti gli elementi devono essere controllati; solo il numero di elementi richiesti dalla catena di chiamata verrà controllato. Esattamente come il tuo 'FirstOrDefault', che andrà a scorrere fino a quando non raggiunge una corrispondenza. –

-1

ho usato

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

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

questo non risponde esattamente alla domanda. L'OP sta chiedendo perché lui/lei non può usare pausa/continua come un normale ciclo. – Rafael

+0

Prova a rimuovere 'do-while' e usa' break', LOL. – code4life

3

return fungerà continue in ForEach.

Esempio:

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

stampe 1, 2, 4.

3 - ignorato.

1

Poiché ForEach è un metodo e non un ciclo foreach regolare è necessario eseguire iterate su lstTemp con un ciclo foreach regolare in caso di interruzione, ma nel caso in cui continuare utilizzare restituire all'interno del metodo ForEach.

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

di uscita: 1, 2, 4