Łamanie / wyjście zagnieżdżone w vb.net

122

Jak wyjść z zagnieżdżonej pętli for lub w vb.net?

Próbowałem użyć wyjścia dla, ale przeskoczyło lub złamało tylko jedną pętlę for.

Jak mogę to zrobić dla następujących:

for each item in itemList
     for each item1 in itemList1
          if item1.text = "bla bla bla" then
                exit for
          end if
     end for
end for
KoolKabin
źródło
To, czego naprawdę potrzebuje VB, to Exit For itemwariant instrukcji, podobny do Next item. W „starych dobrych czasach” można było wyraźnie użyć Nextzewnętrznej pętli. Dzisiaj VB daje błąd. Oczywiście Exit Forzamiast tego jest bardziej „konstruktywne” .
ysap

Odpowiedzi:

199

Niestety nie ma żadnego exit two levels of foroświadczenia, ale istnieje kilka obejść, aby zrobić to, co chcesz:

  • Idź . Ogólnie rzecz biorąc, używanie gotojest uważane za złą praktykę (i słusznie), ale używanie gotowyłącznie do skoku do przodu z ustrukturyzowanych instrukcji sterujących jest zwykle uważane za prawidłowe, zwłaszcza jeśli alternatywą jest posiadanie bardziej skomplikowanego kodu.

    For Each item In itemList
        For Each item1 In itemList1
            If item1.Text = "bla bla bla" Then
                Goto end_of_for
            End If
        Next
    Next
    
    end_of_for:
    
  • Ślepy blok zewnętrzny

    Do
        For Each item In itemList
            For Each item1 In itemList1
                If item1.Text = "bla bla bla" Then
                    Exit Do
                End If
            Next
        Next
    Loop While False
    

    lub

    Try
        For Each item In itemlist
            For Each item1 In itemlist1
                If item1 = "bla bla bla" Then
                    Exit Try
                End If
            Next
        Next
    Finally
    End Try
    
  • Oddzielna funkcja : Umieść pętle w osobnej funkcji, z której można wyjść za pomocą return. Może to jednak wymagać przekazania wielu parametrów, w zależności od tego, ile zmiennych lokalnych używasz w pętli. Alternatywą byłoby umieszczenie bloku w wielowierszowej lambdzie, ponieważ spowoduje to zamknięcie zmiennych lokalnych.

  • Zmienna logiczna : może to sprawić, że kod będzie nieco mniej czytelny, w zależności od liczby posiadanych warstw zagnieżdżonych pętli:

    Dim done = False
    
    For Each item In itemList
        For Each item1 In itemList1
            If item1.Text = "bla bla bla" Then
                done = True
                Exit For
            End If
        Next
        If done Then Exit For
    Next
    
Heinzi
źródło
3
Nie mogę powiedzieć, że którykolwiek z nich jest lepszy od gotoinnego niż funkcja, jeśli ma to sens.
Chris Marisic
2
Mam zamiar użyć tego gotow dużym projekcie tylko po to, aby przypomnieć sobie moje programistyczne dni w qbasic, ach takie niewinne czasy. w przeciwnym razie wybrałbym manekina.
Sharky
1
Wolę podejście Try/ Exit Try, ale nie jestem fanem tej gotoopcji.
JohnH
Zwróć uwagę, że metoda „zmiennej boolowskiej” wymaga wielu zmiennych i testów w miarę pogłębiania poziomu zagnieżdżenia. To staje się
nieznośne
1
@ysap - z mojego doświadczenia wynika, że ​​rzadko potrzeba wielu zmiennych boolowskich. Zwykle istnieje jeden warunek wyjścia (np. „Gotowe”), zgodnie z którym po jego napotkaniu wszystkie poziomy pętli powinny zostać zakończone. Niemniej jednak wolę stworzyć oddzielną metodę i użyć „Return” - to czysto hermetyzuje zagnieżdżoną konstrukcję.
ToolmakerSteve
16

Umieść pętle w podprogramie i wywołaj return

Tobias Schittkowski
źródło
1
Warto zauważyć, że z takim wywołaniem wiąże się narzut, którego nie ma w prostszym gotorozwiązaniu. Oczywiście, jeśli kod jest wielokrotnego użytku, i tak powinien już znajdować się w funkcji.
Dan Bechard
Jak to może być narzut? @Dan
Altiano Gerung
@AltianoGerung Cóż, mój komentarz powyżej zakłada, że ​​kompilator nie optymalizuje i nie wbudowuje wywołania funkcji. Wszystkie wywołania funkcji (zakładając, że nie są wbudowane przez kompilator) mają narzut prologu i epilogu, aby zaktualizować wskaźnik stosu podstawowego (a także wykonywać inne czynności, takie jak wywoływanie destruktorów i czyszczenie pamięci, jeśli język to obsługuje). Jest to często drobiazg w wielkim schemacie rzeczy, ale istnieje i może szybko stać się widoczny w ciasnych pętlach. en.wikipedia.org/wiki/Function_prologue
Dan Bechard
@Dan Cóż, to jest poza mną LOL. Myślę, że biorąc pod uwagę moje przypadki użycia i poprawę technologii w czasie, nigdy nie będę musiał się tym martwić.
Altiano Gerung
2
@AltianoGerung Jeśli czegoś nauczyło mnie doświadczenie, to tego, że przy wystarczającej skali nawet najmniejsze problemy stają się na tyle duże, że mają znaczenie. Jak zawsze, przed dokonaniem jakichkolwiek założeń zarejestruj się. :)
Dan Bechard
3

Uczyń zewnętrzną pętlę pętlą while i „Exit While” w instrukcji if.

Andrew Thomas
źródło
Robi to dokładnie to samo, co w gotoprzypadku większej liczby instrukcji, większej szczegółowości i większej liczby wcięć. Jaki jest sens?
Dan Bechard
3

Kilka razy eksperymentowałem z wpisywaniem „exit for” i zauważyłem, że zadziałało, a VB nie wrzeszczał na mnie. To chyba opcja, ale po prostu źle wyglądała.

Myślę, że najlepsza opcja jest podobna do tej, którą podzielał Tobiasz. Po prostu umieść swój kod w funkcji i pozwól mu wrócić, gdy chcesz wyrwać się z pętli. Wygląda też czysto.

For Each item In itemlist
    For Each item1 In itemlist1
        If item1 = item Then
            Return item1
        End If
    Next
Next
Cesar
źródło
Nie, wielokrotne „Zakończ dla” nie powodują pożądanego zachowania. Pierwsza z nich wychodzi z pierwszej pętli, kolejne nigdy nie są osiągane, więc nie mają żadnego efektu. Poza tą sugestią wydaje się, że po prostu powtórzyłeś wcześniejsze odpowiedzi.
ToolmakerSteve
3
For i As Integer = 0 To 100
    bool = False
    For j As Integer = 0 To 100
        If check condition Then
            'if condition match
            bool = True
            Exit For 'Continue For
        End If
    Next
    If bool = True Then Continue For
Next
Hitesh Paliwal
źródło
Nie używaj tego. Jego zachowanie jest złe. Zamiast tego zobacz przyjęte rozwiązanie „zmiennej boolowskiej” z sześciu lat wcześniej. Gdyby to było nowe podejście, wyjaśniłbym, co powoduje, że zachowuje się nieprawidłowo, ale nie warto tego robić, ponieważ podejście to zostało już poprawnie pokazane we wcześniejszej odpowiedzi.
ToolmakerSteve
0

Jeśli chcę wyjść z pętli for-to, po prostu ustawiam indeks poza limit:

    For i = 1 To max
        some code
        if this(i) = 25 Then i = max + 1
        some more code...
    Next`

Poppa.

Poppa Mintin
źródło
Polecam pokazać, jak to się odnosi do tego pytania. Weź kod z pytania i edytuj go, aby zastosować to podejście.
ToolmakerSteve