Почему я не могу добавить метку goto в конце метода?

Изучив способ выхода из вложенного цикла, я решил попробовать использовать goto,

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:
}

Но по какой-то причине, если я поставлю метку goto в самом конце метода, Visual Studio 2012 (Ultimate) жалуется (и не компилируется),

Скриншот

Но если я изменю свой код на это,

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.
}

Ни одна из ошибок не появляется (и компилируется); Я просмотрел все ссылки MSDN, о которых я знаю, и ничего не нашел по этому поводу.

Я знаю, что могу легко решить эту проблему, используя return;; даже в этом случае я все равно хотел бы выяснить, что вызывает эту ошибку.


person Sam    schedule 30.08.2013    source источник
comment
Я знаю; но это принцип, насколько я понимаю, это должно компилироваться, но это не так.   -  person Sam    schedule 30.08.2013
comment
@Sam: Нет, это действительно не должно :)   -  person Jon Skeet    schedule 30.08.2013
comment
вы должны написать код после метки. Или хотя бы ';' После метки, чтобы визуальная студия могла понять, что после этого кода больше нет.   -  person Tushar Chhabhaiya    schedule 30.08.2013
comment
Зачем вам что-то использовать, даже если вы никогда этого не делали и не должны...?   -  person Austin T French    schedule 30.08.2013
comment
По крайней мере, вы пережили атаку raptor!   -  person Forty-Two    schedule 30.08.2013
comment
@AthomSfere: вполне разумно попытаться понять, почему какой-то код недействителен. Например, goto может быть полезен в автогенерируемом коде. (async/await эффективно генерирует кучу переходов.)   -  person Jon Skeet    schedule 30.08.2013
comment
Это похоже на просмотр пакетного файла Windows 95.   -  person Arran    schedule 30.08.2013
comment
@JonSkeet А, я понимаю, что вы имеете в виду, я думал, что метке goto не нужно указывать метку, чтобы работать. Спасибо за ваш пост.   -  person Sam    schedule 30.08.2013
comment
Жаль, что у нас нет именованных циклов, тогда можно было бы exit loop myOuterLoopName;   -  person Matthew Watson    schedule 30.08.2013
comment
Мне это кажется глупым. В закрывающей фигурной скобке есть подразумеваемый оператор возврата, он присутствует независимо от того, пишем ли мы избыточный оператор или даже пустой оператор (просто точку с запятой) или нет. Конец метода — вполне допустимое место для перехода. Goto МОЖЕТ использоваться для временных изменений во время отладки, что также вполне допустимо. Компилятор не должен спорить с вами из-за несущественных мелочей, подобных этой. Это умнее, чем это. Правильно? Почему просто добавление одной точки с запятой для обозначения нулевого оператора должно исправить этот код? Что получается? Что было бы потеряно, если бы его не было?   -  person    schedule 06.11.2015
comment
Связанный вопрос - принятый ответ в основном совпадает с кодом этого вопроса... и-если-так-почему" title="кто-нибудь все еще использует goto в C Sharp, и если да, то почему"> stackoverflow.com/questions/6545720/   -  person    schedule 06.11.2015


Ответы (6)


Метка не существует сама по себе: она помечает оператор. Из раздела 8.4 спецификации С# 5:

Оператор с меткой позволяет предварять оператор меткой. Помеченные операторы разрешены в блоках, но не разрешены как встроенные операторы.

В этом случае вы применяете метку в конце метода — нет утверждения, что это метка для. Так что компилятор абсолютно прав, отвергая ваш код.

Если вы действительно этого хотите, вы можете добавить метку к избыточному в противном случае оператору возврата:

exitMethod:
    return;
}

... или просто пустое утверждение, как предложил Ирфан. Однако должно быть оператор.

Но я бы не рекомендовал это. Просто измените любой оператор goto exitMethod; на просто return.

person Jon Skeet    schedule 30.08.2013

Вы можете разместить бланк заявления.

Пытаться:

exitMethod: ;            

Но в любом случае, если вы действительно хотите вернуться из текущего метода, используйте оператор return. если метод имеет другой тип возвращаемого значения, чем void,

return (type);

в противном случае

return;
person Irfan    schedule 30.08.2013

В таком случае

goto exitMethod;

эквивалентно простому

return;

и этот план возвращения значительно более читабелен. Поэтому я не понимаю, почему вы хотите это сделать.

person MK.    schedule 30.08.2013

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

У вас есть exitMethod в качестве метки, но в первом примере у вас нет оператора. Вот почему вы получаете ошибку.

перейти к ссылке

person Paddyd    schedule 30.08.2013

Вам нужно что-то для goto сделать. Оно не может быть пустым.

Например:

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();
}
person Sam Leach    schedule 30.08.2013
comment
Ну, технически он прав. Последняя инструкция в методе является своего рода инструкцией возврата, и нет причин не ставить перед ней метку goto. Но почему. - person MK.; 30.08.2013

Две вещи, первый goto НЕ рекомендуется. Это не позволит вам использовать такую ​​метку из-за того, как работают метки. Метка — это идентификатор исходного кода, позволяющий указать на конкретную инструкцию. В случае, если вы пытаетесь, за ним не следует инструкция, и поэтому он не может определить местоположение инструкции. Это вызывает вашу ошибку.

Опять же, вы не должны использовать goto таким образом. Если вам просто нужно выйти из функции, вы можете использовать оператор return;. Если используемый вами стандарт кодирования предписывает только одну точку возврата, попробуйте что-то вроде этого:

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;
}
person Andrew Ring    schedule 30.08.2013
comment
Если OP хочет внести временное изменение в код во время его отладки или изменения, Goto является полезным временным изменением. Твое изменение намного сложнее. - person ; 06.11.2015