55 votes

Comment sortir de 2 boucles sans variable indicateur en C #?

Comme un exemple trivial permet de dire que j'ai la grille suivante et je suis à la recherche d'un particulier des cellules de la valeur. Une fois trouvé, je n'ai plus besoin de traiter les boucles.

foreach(DataGridViewRow row in grid.Rows)
{
    foreach(DataGridViewCell cell in row.Cells)
    {
        if(cell.Value == myValue)
        {
            //Do Something useful
            //break out of both foreach loops.
        }
    }
}

Comment est-ce fait en C#. En Java, je pourrais utiliser une étiquette au nom de l'extérieur de la boucle, puis saut de boucle, mais je n'arrive pas à trouver une équivalence en C#.

Qu'est-ce que le tersest façon de régler ce problème en c#? Je sais que je peux définir un indicateur booléen, et de vérifier dans la boucle externe de sortir de celui-là, mais il semble tout simplement trop verbeux.

Merci,

91voto

Jimmy Points 35501

1

 foreach(DataGridViewRow row in grid.Rows)
   foreach(DataGridView cell in row.Cells)
      if (cell.Value == somevalue) {
         // do stuff
         goto End:
      }
End:
   // more stuff
 

2

 void Loop(grid) {
    foreach(row in grid.Rows)
       foreach(cell in row.Cells)
           if (something) {
               // do stuff   
               return;
           }
}
 

3

 var cell = (from row in grid.Rows.OfType<DataGridViewRow>()
            from cell in row.Cells.OfType<DataGridViewCell>()
            where cell.Value == somevalue
            select cell
   ).FirstOrDefault();

if (cell != null) {
   // do stuff
}
 

60voto

Eric Lippert Points 300275

Bien que bon nombre des solutions ci-dessus soient correctes et répondent à votre question, je prendrais un peu de recul et me demander "existe-t-il une autre façon de représenter plus clairement la sémantique du programme?"

Je serais enclin à écrire le code comme ceci:

 var query = from row in grid.Rows
            from cell in row.Cells
            where cell.Value == myValue
            select cell;
if (query.Any())
{
  // do something useful;
}
 

Pourquoi écrire des boucles? Vous voulez savoir si une collection particulière a un membre particulier, alors écrivez une requête qui pose cette question, puis examinez la réponse.

38voto

mquander Points 32650

La façon la plus agréable est de décomposer la deuxième boucle en une fonction, comme ceci:

 public void DoubleLoop()
{
    for(int i = 0; i < width; i++)
    {
        for(int j = 0; j < height; j++)
        {
            if(whatever[i][j]) break; // let's make this a "double" break
        }
    }
}
 

va à

 public bool CheckWhatever(int whateverIndex)
{
    for(int j = 0; j < height; j++)
    {
        if(whatever[whateverIndex][j]) return false;
    }

    return true;
}

public void DoubleLoop()
{
    for(int i = 0; i < width; i++)
    {
        if(!CheckWhatever(i)) break;
    }
}
 

Bien sûr, n'hésitez pas à simplifier cela avec LINQ ou autre chose (vous pouvez également mettre CheckWhatever dans la condition de boucle.) Ceci est juste une démonstration détaillée du principe.

23voto

JB King Points 10105

Je voudrais simplement envelopper les boucles dans une fonction et faire revenir la fonction comme un moyen de quitter les boucles pour ma solution.

21voto

Timothy Carter Points 7079
         foreach (DataGridViewRow row in grid.Rows)
        {
            foreach (DataGridViewCell cell in row.Cells)
            {
                if (cell.Value == myValue)
                {
                    goto EndOfLoop;
                    //Do Something useful
                    //break out of both foreach loops.
                }
            }

        }
        EndOfLoop: ;
 

cela fonctionnera, mais je recommanderais d'utiliser un drapeau booléen.

ÉDITER: Juste pour ajouter un peu plus d'avertissement ici; il est généralement considéré comme une mauvaise pratique d'utiliser des goto car ils peuvent rapidement conduire à un code spaghetti qui est (presque) impossible à maintenir. Cela étant dit, il a été inclus dans le langage C # et est disponible pour une utilisation, donc il y a clairement des gens qui croient qu'il a des usages valides. Sachez que la fonctionnalité existe et utilisez-la avec beaucoup de prudence.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X