Подтвердить что ты не робот

Использовать "переход" в коммутаторе?

Я видел предложенный стандарт кодирования, который читает Never use goto unless in a switch statement fall-through.

Я не следую. Каково было бы это дело "исключение", что оправдывает goto?

4b9b3361

Ответ 1

Эта конструкция является незаконной в С#:

switch (variable) {
   case 2: 
       Console.WriteLine("variable is >= 2");
   case 1:
       Console.WriteLine("variable is >= 1");
}

В С++ он будет запускать обе строки, если variable = 2. Это может быть преднамеренным, но слишком легко забыть break; в конце метки первого случая. По этой причине они сделали это незаконным в С#. Чтобы воспроизвести падение поведения, вам нужно явно использовать goto, чтобы выразить свое намерение:

switch (variable) {
   case 2: 
       Console.WriteLine("variable is >= 2");
       goto case 1;
   case 1:
       Console.WriteLine("variable is >= 1");
       break;
}

Тем не менее, есть несколько случаев, где goto на самом деле является хорошим решением проблемы. Никогда не закрывайте свой мозг с правилами "никогда не используйте что-то". Если бы это было на 100% бесполезно, вначале оно не существовало бы на этом языке. Не использовать goto является ориентиром; это не закон.

Ответ 2

С# отказывается позволять случаям проходить неявно (если в коде нет кода), как в С++: вам нужно включить break. Чтобы явно провалиться (или перейти в любой другой случай), вы можете использовать goto case. Поскольку нет другого способа получить это поведение, большинство (разумных) стандартов кодирования позволят это.

switch(variable)
{
case 1:
case 2:
    // do something for 1 and 2
    goto case 3;
case 3:
case 4:
    // do something for 1, 2, 3 and 4
    break;
}

Реалистичный пример (по запросу):

switch(typeOfPathName)
{
case "relative":
    pathName = Path.Combine(currentPath, pathName);
    goto case "absolute";

case "expand":
    pathName = Environment.ExpandEnvironmentVariables(pathName);
    goto case "absolute";

case "absolute":
    using (var file = new FileStream(pathName))
    { ... }
    break;

case "registry":
    ...
    break;
}

Ответ 3

   public enum ExitAction {
        Cancel,
        LogAndExit,
        Exit
    }

Это аккуратно

ExitAction action = ExitAction.LogAndExit;
switch (action) {
    case ExitAction.Cancel:
        break;
    case ExitAction.LogAndExit:
        Log("Exiting");
        goto case ExitAction.Exit;
    case ExitAction.Exit:
        Quit();
        break;
}

Чем это (особенно если вы больше работаете в Quit())

ExitAction action = ExitAction.LogAndExit;
switch (action) {
    case ExitAction.Cancel:
        break;
    case ExitAction.LogAndExit:
        Log("Exiting");
        Quit();
        break;
    case ExitAction.Exit:
        Quit();
        break;
}

Ответ 4

В дополнение к использованию goto case вы можете goto метку, которая находится в другом случае:

    switch(i) {
    case "0":
        // do some stuff
        break;
    case "1":
        // other stuff, then "fall through" to next case clause
        goto Case2;
    case "2":
    Case2:
        break;
    }

Таким образом, вы можете перейти к другому аргументу case, не беспокоясь о значении или типе выражения.

Некоторое явное ключевое слово "fallthrough", которое может быть заменено на break, было бы неплохо, хотя...

Ответ 5

Это единственный способ, с помощью которого С# разрешает случай переключения "провал". В С# (в отличие от C, С++ или Java) блок case в операторе switch должен заканчиваться на break или какой-либо другой явный оператор перехода.

Ответ 7

В качестве дополнения к совету Mehrdad Afshari, выше, я бы никогда не выступал просто изгнанием конструкции как "плохой код" или "плохая практика кодирования". Даже "goto" заявления имеют свое место в великой схеме вещей. Догма о том, что они злые, не сбылась из-за каких-либо присущих изъянов в конструкции - это было из-за того, что они были сильно (и плохо) чрезмерно использованы.

В любом случае, Керниган и Ричи чувствовали, что разрешить случай проваливаться - это правильный путь. Честно говоря, я более склонен доверять их рассуждениям, чем все, что могло бы возникнуть из любого ума во всем Редмонде, штат Вашингтон. Или любая догма, которая основана на мудрости любого ума в Редмонде.

Если вы когда-либо слышали "Никогда не используйте xxx", мысленно добавьте это с помощью "без причины". Просто бросать что-нибудь догматически смешно. Устройства существуют, потому что есть причина их создания. Они, оглядываясь назад, обычно называются "плохими" не из-за какой-либо ошибки в самом устройстве, а скорее из-за плохого использования людьми, которые не понимали их полностью. Таким образом, устройство вряд ли "плохо". То, что почти всегда плохо, - это понимание пользователем. Это справедливо даже при делении и слиянии атомов.

Я видел ужасно гротескные структуры кода, единственной функцией которых было избежать использования оператора 'goto'. Что еще хуже? "goto [label]" или 30 строк отвратительного кода, функция которого заключается в том, чтобы не набирать "goto [label]"?

Ищите знания до догмы. Думай прежде чем сделать. Это полезные советы.

Ответ 8

Я знаю, что это старая тема, но вопрос все еще актуален. Можем ли мы использовать следующий код вместо уродливой версии с оператором goto?

var variable = 2;
switch (variable)
{
case 2:
Console.WriteLine("variable is >= 2");
goto case 1;
case 1:
Console.WriteLine("variable is >= 1");
break;


}

может быть заменен следующим кодом:

if (variable >= 2)
{
Console.WriteLine("variable is >= 2");
}
if (variable >= 1)
{
Console.WriteLine("variable is >= 1");
}