Почему я не могу добавить метку 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) жалуется (и не компилируется),

Screenshot

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

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;; тем не менее, я все равно хотел бы узнать, что вызывает эту ошибку.

Ответ 1

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

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

В этом случае вы применяете метку в конце метода - там нет инструкции для нее для метки. Поэтому компилятор абсолютно прав, чтобы отклонить ваш код.

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

exitMethod:
    return;
}

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

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

Ответ 2

Вы можете разместить пустой оператор.

Try:

exitMethod: ;            

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

return (type);

иначе

return;

Ответ 3

В этом случае

goto exitMethod;

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

return;

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

Ответ 4

Вам нужно что-то для 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();
}

Ответ 5

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

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

ссылка goto

Ответ 6

Две вещи, сначала 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;
}