Кто-нибудь все еще использует [goto] в С#, и если да, то почему?
Мне было интересно, все еще использует синтаксис ключевых слов "goto" на С# и какие возможные причины для этого.
Я склонен рассматривать любые утверждения, которые заставляют читателя перескакивать код как плохую практику, но задавались вопросом, существуют ли какие-либо надежные сценарии для использования такого синтаксиса?
Перейти к определению ключевого слова
Ответы
Ответ 1
Есть некоторые (редкие) случаи, когда goto может улучшить читаемость. Фактически в документации, к которой вы привязаны, приведены два примера:
Общее использование goto заключается в передаче управления на конкретную метку ключа коммутатора или метку по умолчанию в инструкции switch.
Оператор goto также полезен для выхода из глубоко вложенных циклов.
Вот пример для последнего:
for (...) {
for (...) {
...
if (something)
goto end_of_loop;
}
}
end_of_loop:
Конечно, есть и другие способы решения этой проблемы, такие как рефакторинг кода в функцию, использование фиктивного блока вокруг него и т.д. (см. этот вопрос для деталей). В качестве стороннего примечания разработчики языка Java решили полностью запретить goto и ввести вместо этого выражение с надписью break.
Ответ 2
Я помню эту часть
switch (a)
{
case 3:
b = 7;
// We want to drop through into case 4, but C# doesn't let us
case 4:
c = 3;
break;
default:
b = 2;
c = 4;
break;
}
Что-то вроде этого
switch (a)
{
case 3:
b = 7;
goto case 4;
case 4:
c = 3;
break;
default:
b = 2;
c = 4;
break;
}
Обратитесь Это
Ответ 3
Я использую его в Eduasync, чтобы показать тип кода, который генерирует компилятор для вас при использовании методов async в С# 5 Вы увидите то же самое в блоках итератора.
В "нормальном" коде, однако, я не могу вспомнить последний раз, когда я его использовал...
Ответ 4
goto отлично подходит для выхода из многих циклов, где перерыв не будет работать хорошо (скажем, при ошибках), и, как сказал Краген, goto используется компилятором для генерации операторов switch и некоторых других вещей.
Ответ 5
Компилятор использует выражения goto
в разных частях сгенерированного кода, например, в сгенерированных типах блока итератора (генерируемых при использовании ключевого слова yield return
). Я уверен, что сгенерированные типы сериализации XML также имеют несколько goto
где-то там.
См. Детали реализации блока Iterator: автогенерированные конечные машины для получения более подробной информации о том, почему и как компилятор С# справляется с этим.
Помимо сгенерированного кода нет веских оснований для использования инструкции goto
в нормальном коде - это делает код более сложным для понимания и, как результат, более подверженным ошибкам. С другой стороны, использование операторов goto
в сгенерированном коде, таком как это, может упростить процесс генерации и нормально нормально, потому что никто не собирается читать (или изменять) сгенерированный код, и нет никаких шансов на ошибку, поскольку машина делает запись.
См. Утверждение Go-to, считающееся вредным для аргумента против goto
, а также классическую часть истории программирования.
Ответ 6
Я не помню когда-либо используя goto
. Но, возможно, это улучшает цель непрерывного цикла, который вы действительно никогда не хотите покидать (нет break
, но вы все еще можете return
или throw
):
forever: {
// ...
goto forever;
}
Затем снова нужно простое while (true)
...
Кроме того, вы можете использовать в ситуации, когда вы хотите, чтобы первая итерация цикла начиналась в середине цикла: посмотрите здесь для примера.
Ответ 7
Процессор реализует хотя бы одну , и я уверен, что многие заявления используют их в реализации или интерпретации.
Одна из хороших вещей об использовании 3rd или 4th langauge - это то, что эти физические детали отвлечены от нас. Хотя мы должны помнить закон нечеткой абстракции Я думаю, что мы также должны использовать наш инструменты, поскольку они предназначены (извините). Если бы я писал код, а goto
казался хорошей идеей, настало время для рефакторинга. Цель структурированного языка - избегать этих "прыжков" и создавать логический поток в нашей технике.
Мне следует избегать использования break
, но я не могу забыть о преимуществах производительности. Однако, если у меня есть вложенные петли, которые взаимно нуждаются в break
, пришло время рефакторировать.
Если кто-нибудь может предложить использовать goto
, который кажется лучше, чем рефакторинг, я с удовольствием отозваю свой ответ.
Надеюсь, я не виновен в том, чтобы спешить с "байковым сараем здесь. Как говорит Краген, достаточно хорошего для Dijkstra для меня достаточно.
Ответ 8
Я смотрел чистый исходный код и нападал на this в свойстве ControlStyle для WebControl
public Style ControlStyle
{
get
{
if (this.controlStyle == null)
{
this.controlStyle = this.CreateControlStyle();
if (base.IsTrackingViewState)
{
this.controlStyle.TrackViewState();
}
if (!this._webControlFlags[1])
{
goto IL_4D;
}
this._webControlFlags.Clear(1);
this.controlStyle.LoadViewState(null);
}
IL_4D:
return this.controlStyle;
}
}
Таким образом, даже Microsoft использует его
Ответ 9
Это особенно хорошо, когда вам нужно очистить перед возвратом из метода, например.
while (stream.Read(buffer, 0, 4) == 4)
{
// do smth with the 4 bytes read here
if (stream.Read(buffer, 0, 4) != 4) goto CLOSE_STREAM_AND_RETURN;
// do more stuff
if (stream.Read(buffer, 0, 4) != 4) goto CLOSE_STREAM_AND_RETURN;
// more stuff
}
CLOSE_STREAM_AND_RETURN:
stream.Close();
Вдохновленный: http://eli.thegreenplace.net/2009/04/27/using-goto-for-error-handling-in-c/
Ответ 10
Гото никогда не бывает лучше. И продолжайте, перерыв (за исключением переключателя/случая), (множественный) возврат, а бросок также должен быть сведен к минимальному минимуму. Вы никогда не хотите убегать от середины петлей гнезд. Вы всегда хотите, чтобы операторы управления циклом имели все элементы управления контуром. Отступы имеют информацию, и все эти утверждения отбрасывают эту информацию. Вы могли бы также вынуть все отступы.