2009-03-19 3 views
9

Этикетки и GOTO s считаются плохой практикой, и насколько я знаю, нет смысла использовать ее в C#.Что такое использование меток в C#?

Что такое использование меток на C#?

+3

Они дают другим программистам причину жаловаться на ваш код :-) –

+0

Возможный дубликат [Кто-нибудь все еще использует \ [goto \] в C#, и если так почему?] (http://stackoverflow.com/questions/6545720/does-anyone-still-use-goto-in-c-sharp-and-if-so-why) –

ответ

19

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

Типичное использование этикетки

OperationStart: 
    if (!TrySomeOperation()) { 
    if (MaybeFixOperation()) { 
     goto OperationStart; 
    } 
    } 

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

+0

Я думаю, что это наиболее распространенное использование из goto. –

+5

«Нет ничего неотъемлемо неправильного с этим кодом» Вы имеете в виду, кроме того, что он не очень читабельны? , если у вас это было написано с помощью: while (! TrySomeOperation() && MaybeFixOperation()) {}, это делает гораздо более очевидным, что вы (возможно, бесконечно) зацикливаетесь. – Aiua

+5

Считываемость находится в глазу читателя. Я последовал за этим хорошо. – Perchik

7

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

2

Я думаю, что это было маркетинговое решение ..

Microsoft хочет, чтобы все виды разработчиков, использующих их C# язык, а если добавить метки, это делает переход для некоторых программистов проще. Это также упрощает перенос старого кода на их язык ...

+0

Для запись: я не ненавижу MS .. Я люблю C# так же, как следующий парень .. и я думаю, что это был умный шаг, чтобы добавить метки и инструкции goto ... – Arcturus

0

Я читал где-то, goto в большинстве случаев должен просто использоваться для прыжков вперед, поэтому, скорее всего, только для ранних контуров цикла и для продолжения внешнего цикла с тех пор в C# нет отмеченных циклов (в отличие от Java). И есть некоторые алгоритмы, которые могут быть элегантно выражены с помощью goto, чем сделать это структурированным способом.

+0

Так я использую gotos. петли, иногда проще просто перейти к некоторой метке, вместо этого пытаясь выяснить, как вырваться из этого цикла. – Perchik

0

Иногда хорошо выполненный 'goto' является более элегантным/читаемым, чем другие методы. Помещение «goto» вокруг, когда они не нужны, - это, конечно, плохая практика. Как всегда, каждая ситуация должна быть тщательно оценена.

Например, «goto's может быть приятным, когда ваша функция должна выполнять очистку в случае ее отказа. Вы помещаете метку в конце функции, где вы выполняете очистку, а затем «переходите» к ней в случае сбоя.

Тем не менее, «goto's стали менее полезными в C#, чем в C. Например, правильное использование обработки исключений может устранить необходимость« goto »в некоторых сценариях.

0

Использование этикеток для поддержки goto. Плохо, как goto может быть, если у вас есть goto на этом языке, вам нужны ярлыки. Без goto ярлыки действительно бесполезны в C#.

6

Когда вы реализуете небольшую finite state machine вы можете использовать метку для каждого состояния и Гото для переходов между состояниями. Это один из стандартных методов имплантации конечных автоматов и может привести к четкому коду, если в документе есть диаграмма конечного автомата, на который указывают комментарии к коду.

Иногда проблемный домен содержит множество состояний machiens (например, протоколы телекоммуникаций часто определяются конечными автоматами), большую часть времени вы часто не видите конечный автомат.

GOTOS и этикетки также очень полезны для машинного кода генерируется, если вы пишете простой компилятор, который выводит C#, вы можете быть очень рад, что из них.

+0

DFA действительно используются довольно много, в общем они используются в токенизаторах и парсерах. Этот подход привел бы к массовым методам ... Вы знаете, что если у вас очень большой метод в IL, он не будет оптимизирован средой выполнения .NET, правильно? По разным причинам обычно лучше, чтобы DFA скомпилировался в шаблон состояния, если вы спросите меня, даже если это код, сгенерированный машиной. – atlaste

2

Этикетки без goto бесполезны, они ничего не делают.

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

foreach(...) { 
    foreach(...) { 
    if(...) { 
     goto OuterLabel; 
    } 
    } 
} 
OuterLabel: 

В таком случае с помощью break заявления будет просто разорвать самый внутренний цикл.

+1

Почему бы не поставить два foreach на внешний вид там собственного метода, тогда вы можете просто использовать оператор return, чтобы вырваться. Большинство примеров goto, которые я видел, находятся в длинных методах, мне не нравятся длинные методы. –

+0

Согласовано, используя отдельный метод, является хорошим подходом, поскольку оператор 'return' способен вырваться из всего метода. –

+5

Некоторые люди (включая меня) не любят создавать методы только для их создания. – Perchik

1

Трудно сделать инструкции переключателей без них.

+0

Это? Кажется, я справляюсь ... Можете ли вы привести пример? – Blorgbeard

+0

Операторы case и default являются метками. Вы можете увидеть это с помощью: переключатель (x) { кейс 1: если (одинEqualsTwo) goto кейс 2; break; кейс 2: break; } Это сделано наиболее ясно в спецификации ECMA для C#: http://www.csharpfriends.com/Spec/index.aspx?specID=15.7.2.htm – mancaus

0

Хотя в принципе я считаю, что есть законное использование для goto заявления, на практике я развивается в C#, так как он был впервые выпущен, и я не знаю, что это не было goto заявления до сих пор.

2

Генераторы кода иногда используют метки и топологи. В некоторых случаях он может упростить логику генерации кода. Операции Goto обычно игнорируются по соображениям удобочитаемости, но если код не предназначен для чтения, то это спорный вопрос.

Я также видел случаи, когда декомпилятор довольно запутывался IL и выводил операторы goto вместо хорошо продуманной последовательности инструкций, которые человек мог бы вызвать. Если операторы goto не были законными, то декомпилятор, возможно, должен был бы полностью использовать этот раздел кода. Таким образом, по крайней мере, он может генерировать что-то, которое может быть отключено.

0

Если (аудитория.LikesGoTo == true) { goto LabelThatSupportGoTo; } прочее { goto LabelForRejectGoTo; }

+0

Подумал об использовании [этой статьи] (http: //www.u.arizona.edu/~rubinson/copyright_violations/Go_To_Considered_Harmful.html) для LabelForRejectGoTo. – Ben

2

Почему это так?

Причина на самом деле довольно проста. Ассемблер и ИЛ не поддерживают расширенные инструкции, такие как for, do, break, continue и while. Неявно, код, который петли (или, в более общем плане, ветви), скомпилирован в ветви. goto и label - очень буквальная ветка.

Обратите внимание, что вы просто не можете реализовать все приспособления, о которых я могу легко думать без «goto» - хотя обычно есть лучшие альтернативы (на данном этапе я хотел бы указать, что существуют шаблоны проектирования, такие как State pattern).

Если вы создаете язык, подобный C#, который является своего рода «ассемблером высокого уровня для IL», имеет смысл поддерживать хотя бы все, что есть в IL. Здесь branch/label - это низкоуровневая конструкция, а goto/label - это проекция C# (с областью, добавленной как конструкция высокого уровня).

От компилятора POV

В конце концов, если вы идете вниз, как работает компилятор, есть разница в предсказуемого кода и непредсказуемой кода. Оптимизирующая часть компилятора тратит огромные усилия на нормализацию конструкций, которые вы используете в своем коде. После нормализации он оптимизирован с использованием шаблонов.

В этом и заключается проблема. Если у вас есть цикл while, цикл for или цикл foreach, он определенно сгенерирует нормализованный шаблон. В конце концов, петли - это номер один в вашем коде, который можно оптимизировать. Однако, если вы используете странные ветви, они не будут оптимизированы - просто потому, что они не будут нормализованы к стандартизованному шаблону и поэтому не будут подхвачены шаблоном.

Этот комментарий не только о предсказуемости шаблонов кода - это также о предсказуемости потока данных. Опять же, если это предсказуемо, ваш компилятор может сделать больше, чем если бы это не так. В различных случаях конструкции, такие как break и continue, также приведут к более непредсказуемым ветвям; ярлыки и goto просто доставят вас туда легче. Результат будет таким же: ваша производительность пострадает, если это произойдет.

Так что, правда, все компиляторы меняют петли на ветви определенной формы. Компилятор IL - это компилятор SSA, как LLVM. Это видео Чандлера объясняет кое-что о том, как это работает: https://www.youtube.com/watch?v=FnGCDLhaxKU

Смежные вопросы