break; und continue frage

  • C#
  • .NET (FX) 4.5–4.8

Es gibt 46 Antworten in diesem Thema. Der letzte Beitrag () ist von BiedermannS.

    break; und continue frage

    Hallöchen,

    ich stehe gerade mal wieder auffem Schlauch....
    Habe folgendes Konstrukt:

    C#-Quellcode

    1. foreach (string username in lb_users.Items)
    2. {
    3. //Hier möchte ich wieder hin *1
    4. while (tmpN < sites + 1)
    5. {
    6. foreach (uservideos.UserVideoCollection vid in vobj.userVideoCollection)
    7. {
    8. //wenn hier if irgendwas true ergibt möchte ich an den anfang der ersten foreach kennzeichnet mit *1
    9. }
    10. }
    11. }


    Wie im Code markiert möchte ich quasi bei na abfrage was prüfen und wenn die true ergibt möchte
    ich direkt weitermachen mit dem nächsten eintrag in der ersten foreach..
    ich weiß das ich mit

    C#-Quellcode

    1. continue;

    den aktuellen durchlauf der nächstgelegenen schleife abbreche und der nächste turn anfängt aber wie komme ich
    zu der obersten foreach ?

    Thema ist gelöst hier aber noch Code wegen Verbesserungen:
    Spoiler anzeigen

    C#-Quellcode

    1. object[] codeString = { "JSON.stringify(window.initials)" };
    2. foreach (string username in lb_users.Items)
    3. {
    4. int curPos = lb_users.Items.IndexOf(username) + 1;
    5. lbl_currentuser.Text = string.Format("Aktuell: {0} | {1} / {2} ", username, curPos, lb_users.Items.Count);
    6. int tmpN = 1;
    7. int vids = 0;
    8. int sites = 0;
    9. string URL = string.Format("https://BEISPIEL.DE/users/{0}/videos", username);
    10. webBrowser1.Navigate(URL); /// VON HIER BIS UNTEN ist natürlich unnötig und kann ich mit
    11. // webrequests natürlich viel besser machen was auch noch kommt.
    12. //Das ganze Webbrowser dingen ändert sich halt noch in webrequests.
    13. while (webBrowser1.ReadyState != WebBrowserReadyState.Complete)
    14. {
    15. Application.DoEvents(); // Darüber brauchen wir nicht reden wie gesagt das ändert sich noch in WebRequests.
    16. }
    17. if (webBrowser1.DocumentText.Contains("This profile is visible to friends only"))
    18. { //Hier ist klar... wenn das profil nur für freunde sichtbar ist kann ich nichts sehen also nächster user:
    19. lb_vidlist.Items.Add(string.Format("Profile: {0} is private", username));
    20. continue;
    21. }
    22. if (!webBrowser1.Url.ToString().Contains("videos"))
    23. { //Hier wird geprüft ob die URL noch den string "videos" enthält wenn nicht wurde weitergeleitet und man
    24. //kann die videos nicht einsehen also auch nicht verwertbar
    25. lb_vidlist.Items.Add(string.Format("Profile: {0} videos not there ^.^ ", username));
    26. continue;
    27. }
    28. var json = webBrowser1.Document.InvokeScript("eval", codeString); //hiermit bekomme ich den JSON-String.
    29. var obj = JsonConvert.DeserializeObject<uservideos.RootObject>((string)json); //sollte klar sein
    30. sites = obj.maxVideoPages; //Viele seiten an videos hat der user.
    31. //// Wenn user schon in datenbank dann weiter sonst eintragen
    32. m_dbConnection = new SQLiteConnection("Data Source=db.db;Version=3;");
    33. m_dbConnection.Open();
    34. SQLiteCommand cmd = new SQLiteCommand(m_dbConnection);
    35. cmd.CommandText = string.Format("SELECT count(*) FROM user WHERE profile_id={0}", obj.profileID);
    36. int count = Convert.ToInt32(cmd.ExecuteScalar());
    37. if (count == 0)
    38. {
    39. cmd.CommandText = string.Format("INSERT INTO user(profile_id,n_vids) VALUES ({0},{1})", obj.profileID, obj.profile._counts.video);
    40. cmd.ExecuteNonQuery();
    41. }
    42. //// Wenn user schon in datenbank dann weiter sonst eintragen ENDE
    43. SQLiteCommand cmdvid = new SQLiteCommand(m_dbConnection);
    44. while (tmpN < sites+1) //so oft durchlaufen wie seiten mit videos da sind.
    45. {
    46. bool skip = false;
    47. lbl_currentVidSite.Text = string.Format("{0} / {1}", tmpN, sites);
    48. //MessageBox.Show(tmpN.ToString());
    49. string vURL = string.Format("https://BEISPIEL.DE/users/{0}/videos/{1}", username, tmpN);
    50. webBrowser1.Navigate(vURL); //immer noch wird noch umgebaut <3
    51. while (webBrowser1.ReadyState != WebBrowserReadyState.Complete)
    52. {
    53. Application.DoEvents(); //brauch man nicht drüber reden...
    54. }
    55. var vjson = webBrowser1.Document.InvokeScript("eval", codeString); //hier wieder das gleiche... bekomme damit den JSON-String
    56. var vobj = JsonConvert.DeserializeObject<uservideos.RootObject>((string)vjson);
    57. foreach (uservideos.UserVideoCollection vid in vobj.userVideoCollection)
    58. {
    59. cmdvid.CommandText = string.Format("SELECT count(*) FROM vids WHERE vid_id={0}", vid.id);
    60. //Wenn das video schon vorhanden ist dann SKIP (also das PRoblem worum es im Thread geht.
    61. int vcount = Convert.ToInt32(cmdvid.ExecuteScalar());
    62. if (vcount == 0)
    63. {
    64. //ansonsten in die Datenbank aufnehmen
    65. cmdvid.CommandText = string.Format("INSERT INTO vids(vid_id,profile_id,vid_name) VALUES ({0},{1}, @p1)", vid.id, obj.profileID);
    66. cmdvid.Parameters.Add(new SQLiteParameter("@p1", vid.title));
    67. cmdvid.ExecuteNonQuery();
    68. string tName = String.Format("Username: {0} / Title: {1}", username, vid.title);
    69. lb_vidlist.Items.Add(tName);
    70. //und dann ein datei erstellen für jdownloader somit wird das dann runtergeladen.
    71. StreamWriter writer = new StreamWriter(vid.id + ".crawljob", false);
    72. writer.WriteLine("#" + vid.id);
    73. writer.WriteLine("text=" + vid.pageURL);
    74. writer.WriteLine("enabled=true");
    75. writer.WriteLine("autoStart=TRUE");
    76. writer.WriteLine("extractAfterDownload=TRUE");
    77. writer.WriteLine("autoConfirm=TRUE");
    78. writer.Close();
    79. writer.Dispose();
    80. string pathto = @"F:\Tools\JDownloader\folderwatch";
    81. string filename = vid.id + ".crawljob";
    82. File.Move(filename, Path.Combine(pathto, filename));
    83. vids += 1;
    84. } else
    85. { //Hier der skip
    86. skip = true;
    87. break;
    88. }
    89. }
    90. tmpN += 1;
    91. if (skip == true) {
    92. lb_vidlist.Items.Add(string.Format("SKIPPING USER: {0}", username));
    93. break; }
    94. }
    95. m_dbConnection.Close();
    96. //MessageBox.Show(vids.ToString());
    97. }

    Grüße , xChRoNiKx

    Nützliche Links:
    Visual Studio Empfohlene Einstellungen | Try-Catch heißes Eisen

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „xChRoNiKx“ ()

    @xChRoNiKx Du musst zwei Schleifen verlassen, also musst Du auch zwei breaks machen.
    Nutze dazu ein Flag, dass Du bei der äußeren Schleife weißt, dass Du sie verlassen musst.
    Falls danach noch weiterer Code kommt, musst Du den mit continue überspringen, um zum Schleifenanfang zu kommen.
    Spoiler anzeigen

    C#-Quellcode

    1. foreach (string username in lb_users.Items)
    2. {
    3. //Hier möchte ich wieder hin *1
    4. bool exit = false;
    5. while (tmpN < sites + 1)
    6. {
    7. foreach (uservideos.UserVideoCollection vid in vobj.userVideoCollection)
    8. {
    9. //wenn hier if irgendwas true ergibt möchte ich an den anfang der ersten foreach kennzeichnet mit *1
    10. if (DEINE_BEDINGUNG)
    11. {
    12. exit = true;
    13. break;
    14. }
    15. }
    16. if (exit)
    17. {
    18. break;
    19. }
    20. }
    21. if (exit)
    22. {
    23. continue;
    24. }
    25. // falls hier weiterer Code kommt
    26. }

    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    C#-Quellcode

    1. foreach (string username in lb_users.Items)
    2. {
    3. //Hier möchte ich wieder hin *1
    4. bool exit = false;
    5. while (!exit && tmpN < sites + 1)
    6. {
    7. foreach (uservideos.UserVideoCollection vid in vobj.userVideoCollection)
    8. {
    9. //wenn hier if irgendwas true ergibt möchte ich an den anfang der ersten foreach kennzeichnet mit *1
    10. if (DEINE_BEDINGUNG)
    11. {
    12. exit = true;
    13. break;
    14. }
    15. }
    16. }
    17. if (exit)
    18. continue;
    19. // falls hier weiterer Code kommt
    20. }

    find ich etwas schöner ;)
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Um geschachtelte Schleifen zu verlassen, ist es am einfachsten goto zu verwenden. Dies wird auch so in der offiziellen MSDN Dokumentation empfohlen. Kontrollvariablen und irgendwelche if (exit) im Schleifenkörper zu verstreuen ist IMO ziemlicher Murks. goto sollte halt bloß nicht anstatt von If- und Schleifenanweisungen verwendet werden (Spaghtetticode), aber goto mittels Schleifen- und If-Anweisungen nachzubilden ist genauso unsinnig.


    C#-Quellcode

    1. foreach (string username in lb_users.Items)
    2. {
    3. //Hier möchte ich wieder hin *1
    4. while (tmpN < sites + 1)
    5. {
    6. foreach (uservideos.UserVideoCollection vid in vobj.userVideoCollection)
    7. {
    8. //wenn hier if irgendwas true ergibt möchte ich an den anfang der ersten foreach kennzeichnet mit *1
    9. if (bedingung)
    10. goto exit;
    11. }
    12. }
    13. // weiterer code
    14. exit:
    15. }

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Quadsoft“ ()

    EaranMaleasi schrieb:

    Ich lass aus Prinzip meine Finger von goto
    Kann ich nur unterschreiben.
    Auch wenn es in der MSDN steht, bei mir ist goto ein NoGo.
    Seht Euch mal im IlSpy an, wie Select / switch-Anweisungen zurückübersetzt werden. Brrrrrr. <X
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    ich find - um aus verschachtelten Schleifen zu hopfen - goto besser als das zusätzliche HIlfsvariablen einzuführen, die dann an mehreren Stellen abgefragt werden, in jeder Umdrehung.
    Allerdings gibts ja auch Mittel, um verschachtelte Schleifen von vornherein zu vermeiden: .FindIndex, First, FirstOrDefault und Konsorten sind ja im Grunde einfache Standard-Such-Schleifen, in Methoden ausgelagert, und als Einzeiler verwendbar.
    Heyho,
    das ganze ist ja hier über Nacht eskaliert :P
    Mache das jetzt so wie @RodFromGermany geschrieben hatte.
    Allerdings hatte ich garnicht an "goto" gedacht da ich immer der Meinung war C# könnte das garnicht.
    Aber da hat man wieder was dazu gelernt. Ich denke hier wäre dann auch ein goto kürzer und eleganter
    als die if-anweisung aber ich an sich sollte es erstmal funktionieren.
    Der Code wird eh nochmal neu geschrieben damit der schöner ist ^^ Prototyp halt :P
    Grüße , xChRoNiKx

    Nützliche Links:
    Visual Studio Empfohlene Einstellungen | Try-Catch heißes Eisen

    xChRoNiKx schrieb:

    Ich denke hier wäre dann auch ein goto kürzer und eleganter


    Anstatt eines Goto wäre hier ehere eine besseres Datenmodell angebracht welches sich leicht filtern lässt. Dann hast du keine Schleifen mehr und brauchst weder mehrere Breaks, noch Goto.

    Goto sollte in der allgemeinen Applikationsprogrammierung nicht mehr verwendet bzw. empfohlen werden.
    SWYgeW91IGNhbiByZWFkIHRoaXMsIHlvdSdyZSBhIGdlZWsgOkQ=

    Weil einfach, einfach zu einfach ist! :D
    Das hat nichts mit dem Datenmodell zu tun, es gibt genügend Algorithmen wo soetwas nötig ist.

    goto ist in diesem Falle auch gar nicht so schlecht. Warum man goto eigt. immer gerne vermeidet ist, weil es den Code gerne unübersichtlich macht, weil es nunmal Leute gibt, die es für alles mögliche andere Verwenden. Aber in diesem Fall ist es besser lesbar als eine zusätzliche Variable.
    C++ optimiert z.B. außerdem die zusätzliche Variable manchmal weg und macht selbst einen einfachen Sprung daraus.
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---

    BiedermannS schrieb:

    Goto sollte in der allgemeinen Applikationsprogrammierung nicht mehr verwendet bzw. empfohlen werden.
    Dassis deine Meinung.
    Andere meinen - wie gesagt - wenn der Verzicht auf Goto bedeutet, zusätzliche Hilfs-Variablen einzuführen und an mehreren Stellen abzufragen - dann ist Goto das geringere Übel.
    Auch die Einführung zusätzlicher Hilfs-Funktionen kann als fragwürdig angesehen werden - mag der eine oder andere meinen.

    Also um ein pauschales "sollte in der allgemeinen Applikationsprogrammierung nicht mehr verwendet werden" rauszuhauen müssteste besser begründen (meine Meinung ;) )

    jvbsl schrieb:

    Das hat nichts mit dem Datenmodell zu tun, es gibt genügend Algorithmen wo soetwas nötig ist.


    Du kannst grundsätzlich immer zuerst deine Daten filtern und danach mit den gefilterten Ergebnissen arbeiten. Manchmal ist es dafür halt notwendig das Datenmodell zu verbessern.

    Goto sollte definitiv nicht mehr verwendet werden. Dass der Compiler das aus Optimierungsgründen macht ist mir bewusst. Und dass alle If und Switch statements zu Jumps kompiliert werden ist mir auch bewusst, aber das sind Dinge die ein Compiler machen soll, kein Programmierer.

    Edit:

    ErfinderDesRades schrieb:

    Also um ein pauschales "sollte in der allgemeinen Applikationsprogrammierung nicht mehr verwendet werden" rauszuhauen müssteste besser begründen (meine Meinung )

    Soll ich dir die 1000 Artikel heraussuchen in denen das bis ins letzte Detail erklärt wird heraussuchen?

    Natürlich gibt es noch Edge Cases in denen ein Goto die beste Lösung ist, allerdings sind das so wenige, dass man die wahrscheinlich auf einer Hand abzählen kann. Und das hier ist definitiv keiner davon.
    SWYgeW91IGNhbiByZWFkIHRoaXMsIHlvdSdyZSBhIGdlZWsgOkQ=

    Weil einfach, einfach zu einfach ist! :D