web-dev-qa-db-fra.com

Comment échapper à une boucle while en C #

J'essaie d'échapper à une boucle while. Fondamentalement, si la condition "si" est remplie, j'aimerais pouvoir quitter cette boucle:

private void CheckLog()
{
    while (true)
    {
        Thread.Sleep(5000);
        if (!System.IO.File.Exists("Command.bat"))
            continue;

        using (System.IO.StreamReader sr = System.IO.File.OpenText("Command.bat"))
        {
            string s = "";
            while ((s = sr.ReadLine()) != null)
            {
                if (s.Contains("mp4:production/CATCHUP/"))
                {
                    RemoveEXELog();

                    Process p = new Process();
                    p.StartInfo.WorkingDirectory = "dump";
                    p.StartInfo.FileName = "test.exe";
                    p.StartInfo.Arguments = s;
                    p.Start();

                    << Escape here - if the "if" condition is met, escape the loop here >>
                }
            }
        }
    }
}
56
James

Utilisation break; pour échapper à la première boucle:

if (s.Contains("mp4:production/CATCHUP/"))
{
   RemoveEXELog();
   Process p = new Process();
   p.StartInfo.WorkingDirectory = "dump";
   p.StartInfo.FileName = "test.exe"; 
   p.StartInfo.Arguments = s; 
   p.Start();
   break;
}

Si vous souhaitez également échapper à la deuxième boucle, vous devrez peut-être utiliser un indicateur et vérifier la protection de la boucle extérieure:

        boolean breakFlag = false;
        while (!breakFlag)
        {
            Thread.Sleep(5000);
            if (!System.IO.File.Exists("Command.bat")) continue;
            using (System.IO.StreamReader sr = System.IO.File.OpenText("Command.bat"))
            {
                string s = "";
                while ((s = sr.ReadLine()) != null)
                {
                    if (s.Contains("mp4:production/CATCHUP/"))
                    {

                        RemoveEXELog();

                        Process p = new Process();
                        p.StartInfo.WorkingDirectory = "dump";
                        p.StartInfo.FileName = "test.exe"; 
                        p.StartInfo.Arguments = s; 
                        p.Start();

                        breakFlag = true;
                        break;
                    }
                }
            }

Ou, si vous voulez simplement quitter la fonction complètement à l'intérieur de la boucle imbriquée, insérez un return; au lieu d'une break;.

Mais ce ne sont pas vraiment considérés comme des meilleures pratiques. Vous devriez trouver un moyen d'ajouter la logique booléenne nécessaire à vos gardes while.

69
Dirk

break ou goto

while ( true ) {
  if ( conditional ) {
    break;
  }
  if ( other conditional ) {
    goto EndWhile;
  }
}
EndWhile:
9
zellio

Mais vous voudrez peut-être aussi vous pencher sur approche très différente, écouter les événements du système de fichiers .

6
Tim

Si vous devez continuer à utiliser une logique supplémentaire ...

break;

ou si vous avez une valeur à retourner ...

return my_value_to_be_returned;

Cependant, en regardant votre code, je pense que vous contrôlerez la boucle avec l'exemple révisé ci-dessous sans utiliser de pause ou de retour ...

private void CheckLog()
        {
            bool continueLoop = true;
            while (continueLoop)
            {
                Thread.Sleep(5000);
                if (!System.IO.File.Exists("Command.bat")) continue;
                using (System.IO.StreamReader sr = System.IO.File.OpenText("Command.bat"))
                {
                    string s = "";
                    while (continueLoop && (s = sr.ReadLine()) != null)
                    {
                        if (s.Contains("mp4:production/CATCHUP/"))
                        {
                            RemoveEXELog();

                            Process p = new Process();
                            p.StartInfo.WorkingDirectory = "dump";
                            p.StartInfo.FileName = "test.exe"; 
                            p.StartInfo.Arguments = s; 
                            p.Start();
                            continueLoop = false;
                        }
                    }
                }
            }
        }
4
Alban

Quelle boucle essayez-vous de sortir? Un simple break; quittera la boucle intérieure. Pour la boucle externe, vous pouvez utiliser une variable de portée externe (par exemple, boolean exit = false;), définie sur true juste avant de casser votre boucle interne. Après le bloc de boucle interne, vérifiez la valeur exit et, si true, utilisez break; encore.

2
tomfumb

"break" est une commande qui sort de la boucle "la plus proche".

Bien qu'il existe de nombreux bons usages pour la pause, vous ne devriez pas l'utiliser si vous n'y êtes pas obligés - cela peut être vu comme une autre façon d'utiliser goto, ce qui est considéré comme mauvais.

Par exemple, pourquoi pas:

while (!(the condition you're using to break))
        {
         //Your code here.
        }

Si vous utilisez "break" parce que vous ne voulez pas continuer à exécuter cette itération de la boucle, vous pouvez utiliser le mot clé "continue", qui passe immédiatement à la prochaine itération de la boucle, que ce soit que ce soit pendant ou pour.

while (!condition) {
   //Some code
   if (condition) continue;
   //More code that will be skipped over if the condition was true
}
1
Jeremy

Désolé pour le necro-add, mais il y a quelque chose que je voulais vraiment insérer qui manque dans les réponses existantes (pour quelqu'un comme moi tombant sur cette question via Google): refactoriser votre code. Non seulement cela facilitera la lecture/la maintenance, mais cela éliminera souvent ces types de problèmes de contrôle-routage.

Voici ce sur quoi je m'approcherais si je devais programmer la fonction ci-dessus:

private const string CatchupLineToIndicateLogDump = "mp4:production/CATCHUP/";
private const string BatchFileLocation = "Command.bat";

private void CheckLog()
{
    while (true)
    {
        Thread.Sleep(5000);
        if (System.IO.File.Exists(BatchFileLocation))
        {
            if (doesFileContainStr(BatchFileLocation, CatchupLineToIndicateLogDump))
            {
                RemoveLogAndDump();
                return;
            }
        }
    }
}

private bool doesFileContainStr(string FileLoc, string StrToCheckFor)
{
  // ... code for checking the existing of a string within a file
  // (and returning back whether the string was found.)
}

private void RemoveLogAndDump()
{
  // ... your code to call RemoveEXELog and kick off test.exe
}
0
Kevin