2013-08-30 22 views
12

Po zbadaniu sposób, aby wyjść zagnieżdżonych pętli, postanowiłem spróbować użyć goto,Dlaczego nie mogę dodać etykiety goto na końcu metody?

private void example() 
{ 
    for (int i = 0; i < 100; i++) 
    { 
     for (int ii = 0; ii < 100; ii++) 
     { 
      for (int iii = 0; iii < 100; iii++) 
      { 
       goto exitMethod; 
      }     
     }    
    } 

exitMethod: 
} 

Ale z jakiegoś powodu, jeśli mogę umieścić goto etykieta jest na samym końcu tej metody, Visual Studio 2012 (ostatecznym) narzeka (i nie będzie skompilować),

Screenshot

Ale jeśli mogę zmienić kod do tego,

private void example() 
{ 
    for (int i = 0; i < 100; i++) 
    { 
     for (int ii = 0; ii < 100; ii++) 
     { 
      for (int iii = 0; iii < 100; iii++) 
      { 
       goto exitMethod; 
      }     
     }    
    } 

exitMethod: 

    int someUnneededVariable; // Just an example, if I add ANY piece of code the error vanishes. 
} 

Żaden z błędów nie pojawia się (i kompiluje); Przeszukałem wszystkie referencje MSDN, które znam i nie mogłem nic na ten temat znaleźć.

Wiem, że mogę łatwo rozwiązać ten problem, używając return;; mimo to nadal chciałbym dowiedzieć się, co powoduje ten błąd.

+0

Wiem; ale to jest zasada, z mojego rozumienia to powinno się kompilować, ale tak nie jest. – Sam

+1

@Sam: Nie, to naprawdę nie powinno :) –

+0

powinieneś napisać kod po etykiecie. Lub atlease "; ' Po naklejce, aby studio graficzne zrozumiało, że po tym nie ma więcej kodu. –

Odpowiedz

18

Etykieta nie istnieje na własną rękę: to etykiety na oświadczenie. Z sekcji 8.4 specyfikacji C# 5:

Oświadczenie oznaczone etykietą pozwala na dodanie prefiksu do etykiety. Oznakowane instrukcje są dozwolone w blokach, ale nie są dozwolone jako instrukcje osadzone.

W tym przypadku, starasz etykietę na końcu metody - nie ma rachunek za to być etykieta dla. Tak więc kompilator ma absolutną rację, że odrzuca twój kod.

Jeśli naprawdę chciał, mógłbyś dodać etykietę do skądinąd-nadmiarowych instrukcji return:

exitMethod: 
    return; 
} 

... czy tylko pusty oświadczenie, zgodnie z sugestią Irfan. Musi być jednak oświadczenie.

Ale nie poleciłbym tego. Po prostu zmień dowolne oświadczenie goto exitMethod; na po prostu return.

1

W tym przypadku

goto exitMethod; 

odpowiada tylko zwykły

return; 

i że powrót plan jest znacznie bardziej czytelny. Więc nie rozumiem, dlaczego chciałbyś to zrobić.

0

Potrzebujesz czegoś, aby wykonać goto. Nie może być puste.

Na przykład:

private void example() 
{ 
    for (int i = 0; i < 100; i++) 
    { 
     for (int ii = 0; ii < 100; ii++) 
     { 
      for (int iii = 0; iii < 100; iii++) 
      { 
       goto exitMethod; 
      }     
     }    
    } 

exitMethod: 
    int i = DoSomething(); 
} 
+0

Cóż, technicznie on ma rację. Ostatnią instrukcją w tej metodzie jest jakaś instrukcja "return" i nie ma powodu, aby nie umieszczać przed nią etykiety goto. Ale dlaczego. –

0
"The goto statement transfers the program control directly to a labeled statement." 

Masz exitMethod jako swoją etykietę, ale w pierwszym przykładzie nie masz żadnych oświadczeń. Właśnie dlatego pojawia się błąd.

goto reference

9

można umieścić pusty oświadczenie.

Spróbuj:

exitMethod: ;    

Ale tak czy inaczej, jeśli naprawdę chcesz, aby powrócić z obecnym sposobem, zestawienie użycie powrót. jeśli metoda ma inny typ zwracany niż nieważne,

return (type); 

inaczej

return; 
0

dwie rzeczy, NIE jest zalecany pierwszy goto. Nie pozwoli ci używać takiej etykiety z powodu działania etykiet. Etykieta jest identyfikatorem kodu źródłowego pozwalającym wskazać określoną instrukcję. W przypadku, gdy próbujesz, nie ma instrukcji następującej po nim, a zatem nie może on rozwiązać lokalizacji instrukcji. Powoduje to błąd.

Ponownie, nie powinieneś używać w ten sposób goto. Jeśli chcesz po prostu wyjść z funkcji, możesz użyć instrukcji return;. Jeśli standard kodowania, którego używasz, określa tylko jeden punkt zwrotny, spróbuj coś takiego:

private void example() 
{ 
    bool escaping = false; 
    for (int i = 0; i < 100 && !escaping; i++) 
    { 
     for (int ii = 0; ii < 100 && !escaping; ii++) 
     { 
      for (int iii = 0; iii < 100 && !escaping; iii++) 
      { 
       escaping = true; 
       break; // this is only needed if there is code farther down this 
         // inner loop that would otherwise be executed. 
      }     
     }    
    } 

return; 
} 
+0

Jeśli OP chce wprowadzić tymczasową zmianę kodu podczas jego debugowania lub modyfikacji, Goto jest użyteczną zmianą tymczasową. Twoja zmiana jest znacznie trudniejsza. –