Хтось все ще використовує [goto] в C # і якщо так, то чому? [зачинено]


104

Мені було цікаво, чи все ще хтось використовує синтаксис ключових слів «goto» у C # та які можливі причини для цього.

Я схильний розглядати будь-які твердження, які змушують читача стрибати навколо коду як погану практику, але цікаво, чи існують якісь надійні сценарії використання такого синтаксису?

Визначення ключового слова


3
що ти маєш на увазі "все-таки"? Чи був період часу, коли люди користувались ним весь час [в c #]?
Масив

4
@Massif: "все ще" мав на меті підкреслити сучасну думку про використання "goto" як прелюдії до коду спагетті та недостатньої читальності у вихідному коді. Дуже рідко ви бачите приклади коду, включаючи саме це ключове слово, і саме тому мені було цікаво запитати в першу чергу.
Брайан Скотт

50
Якщо читач "стрибає" код - це погана практика, то чи уникаєте ви також "зламати", "продовжити", "кинути" та "повернути"? Всі вони викликають гілку в контрольному потоці, іноді - немісцеву гілку. "Кинь" навіть не каже тобі, куди йде, на відміну від гото.
Ерік Ліпперт

2
Я використовую, gotoщоб перервати цикл і повернутися до початкового висловлення відповідно до конкретної умови
Нітін Сован

3
Мені подобається гото. Я намагався уникати цього через те, що люди говорять, що уникати цього, оскільки це робить код важче читати. Навчившись мови мови складання та галузевих висловлювань, я думаю, що іноді бувають випадки, це може зробити код читабельнішим. Я думаю, що багаторазове використання одного методу і занадто далеко в коді можуть принести більше шкоди, ніж користі. Але якщо ви думаєте, що гото працював би тут непогано, простий гото час від часу не повинен змушувати вас виходити зі свого шляху, щоб уникнути лише тому, що загальний консенсус - це уникати.
eaglei22

Відповіді:


93

Є деякі (рідкісні) випадки, коли goto може фактично покращити читабельність. Насправді документація, яку ви пов’язали, містить два приклади:

Загальне використання goto полягає в передачі керування на конкретну мітку регістру комутатора або мітку за замовчуванням в операторі комутатора.

Оператор goto також корисний для виходу з глибоко вкладених циклів.

Ось приклад для останнього:

for (...) {
    for (...) {
        ...
        if (something)
            goto end_of_loop;
    }
}

end_of_loop:

Звичайно, існують і інші способи вирішення цієї проблеми, такі як рефакторинг коду у функцію, використання макетного блоку навколо нього тощо (детальніше див. Це питання ). В якості додаткового зауваження, дизайнери мови Java вирішили повністю заборонити goto та запровадити замість нього заяву про перерву .


47
Як правило, я б спробував переробити це, щоб розмістити петлі окремим методом, з якого я міг би просто повернутися з ...
Джон Скіт

2
@Heinzi - Я не бачив, щоб Goto було гарантовано. Як каже Джон, якщо це "гарантовано", код просить бути відновленим.
manojlds

29
позначений перервою, просто довший спосіб сказати гото, тому що він робить те ж саме чудотворне ....
Ісус Рамос

20
@ Ісус, але потім з goto, ви можете піти куди завгодно. Помічений перерва гарантує, що ви переходите просто за межі петлі.
mihsathe

1
Якщо ви не займаєтеся авантюризмом і не використовуєте goto з адресою (я це бачив раніше), цю проблему можна усунути. І я сумніваюся, що хтось використовує гачки об'їзду у вашому C # та Java-коді для використання goto-операторів.
Ісус Рамос

65

Я пам’ятаю цю частину

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

Посилайтеся на це


17
Я насправді вважаю це найбільш вагомою причиною використання [goto] поки. Принаймні, у цьому сценарії це збільшує читабельність для програмістів, які не знають, що випадки потрапляють один у одного без заяви про перерву.
Брайан Скотт

11
@Brian Scott, V4Vendetta. Якщо я не помиляюся, перше твердження не складається в C #. Це допомогло б зрозуміти програмісту.
Jodrell

2
V4Vendetta, чому ти вставив перерву на перший фрагмент коду ...? Краще було це показати без перерви, інакше два фрагменти роблять різні речі. Причина, чому вам потрібен goto у другому прикладі, полягає саме в тому, що перший не компілюється в C # (як це було б у C).
Стівен Холт

23

Я широко використовую його в Eduasync, щоб показати тип коду, який створює компілятор для вас при використанні методів асинхронізації в C # 5. Ви б побачили те саме в блоках ітераторів.

У "звичайному" коді, однак, я не можу згадати останній раз, коли я його використовував ...


1
Ви можете навести невеликий приклад того, чому цей підхід був кращим або це був просто особистий уподобання?
Брайан Скотт

1
@Brian: Не зовсім зрозуміло, що ти маєш на увазі. Eduasync показує еквівалентний C # код тому, що робить компілятор для вас, - і він генерує код, який ефективно використовує goto ...
Jon Skeet

9

goto чудово підходить для виходу з багатьох циклів, коли брейк не спрацював добре (скажімо, за умов помилки), і, як сказав Краген, компілятор використовує goto для створення операторів перемикання та інших речей.


7
Безумовно, "перерва" / "продовження" є кращими підходами до управління циклом, а не вимагати редактора коду стрибати навколо вихідного коду, намагаючись зрозуміти, де відбувається наступний крок?
Брайан Скотт

6
Ні, якщо ви вклали петлі.
Ісус Рамос

1
добре, я можу сприймати це як дійсний сценарій.
Брайан Скотт

1
У випадку помилки, вам слід розглянути можливість викидання виключення.
Jodrell

6
Якщо ви хочете вирішити помилку всередині країни без винятку, це був би дійсний спосіб зробити це.
Ісус Рамос

8

Я не пам'ятаю, щоб ніколи користувався goto. Але, можливо, це покращує наміри вічного циклу, з якого ви дійсно ніколи не хочете виходити (ні break, але ви все одно можете returnабо throw):

forever: {
  // ...
  goto forever;
}

Потім знову простого while (true)повинно вистачити ...

Крім того, ви можете використовувати в ситуації, коли ви хочете, щоб перша ітерація циклу почалася посередині циклу: шукайте тут приклад.


Відповідна відповідь містить "цікаве" використання goto.. та while(true) {..}не цікаве використання ..
user2864740

5

Компілятор використовує gotoоператори у різних фрагментах згенерованого коду, наприклад, у створених блоках ітератора блоків (згенерованих під час використання yield returnключового слова - я майже впевнений, що у створених типах серіалізації XML також є gotoдесь там.

Докладніше про те, чому / як компілятор C # справляється з цим, див. Подробиці впровадження блоку Iterator: автоматично створені машини стану .

Окрім згенерованого коду, це не є вагомою причиною використовувати gotoоператор у звичайному коді - це робить його складнішим для розуміння і, як результат, більш схильним до помилок. З іншого боку, використовуючиgoto операторів у згенерованому коді, як це, може спростити процес генерації і нормально нормально, оскільки ніхто не збирається читати (або змінювати) згенерований код, і немає шансів помилок, оскільки машина виконує написання.

Дивіться заяву Go-to, що вважається шкідливою як для аргументу, gotoтак і для класичного фрагмента історії програмування.


4
Це нерозумно: є кілька випадків, коли гото було корисним, як проілюстровано іншими відповідями. Або ви чітко їх протираєте, або просто говорите "це неправильно" - це, ну, неправильно.
o0 '.

@Lohoris Я не купую цього - кожен приклад, який я бачив, де goto "покращує читабельність" (включаючи відповіді тут), був би набагато легше читати після простого рефакторингу.
Джастін

3
@ Джастін ні, іноді вкладені петлі - це лише найприродніший спосіб зробити щось, наприклад, якщо ви проїжджаєте масив масивів.
o0 '.

6
@Justin не завжди зрозуміліше це ввести у функцію. Ви змушуєте щось (маючи функцію) просто, щоб уникнути чогось ненавидіти релігійно (використовуючи гото). Чітка вказівка ​​на те, що робите щось не так
o0 '.

3
@ Джустін Функції дзвінків накладні. gotoне. Щось врахувати.
Ден Бешард

2

Процесор реалізує принаймні одну інструкцію про перехід, і я впевнений, що багато тверджень використовують ті, що використовуються в їх реалізації або інтерпретації.

Однією з хороших речей щодо використання мовного мовлення третього чи четвертого поколінь є те, що ці фізичні деталі віддаляються від нас. Хоча ми повинні пам’ятати про закон протікання абстракції, я думаю, що ми також повинні використовувати наші інструменти так, як вони призначені ( вибачте ). Якби я писав код і аgoto здавався гарною ідеєю, настав би час рефакторингу. Мета структурованої мови - уникнути цих «стрибків» та створити логічний потік у нашій інженерії.

Я повинен уникати використання, breakале не можу не помітити переваги продуктивності. Однак, якщо я вклав петлі, які взаємно потребують, breakсаме час переробляти.

Якщо хтось може запропонувати використовувати goto це, здається, краще, ніж рефакторинг, я із задоволенням відкликаю свою відповідь.

Я сподіваюся, що я не винен у тому, що кинувся сюди до " сараю велосипедів ". Як Kragen каже, Що досить добре для Дейкстри є досить хорошим для мене.


1
Взяття dynamicоб’єкта та прогулянка по його об’єктному графіку, що містить кілька словників, щоб перейти до потрібних мені значень. Не має сенсу використовувати методи, у яких параметр dynamicще очікує точної форми об'єкта. За допомогою goto вирвете кілька шарів і продовжуйте прогулянку по колекції цих об'єктів. [У мене не є типи, тому я не можу забезпечити кращий доступ, тому рефлексія чи динаміка це є]
Chris Marisic

-6

Гото ніколи не кращий. І продовжуйте, перервайте (за винятком перемикача / корпусу), (багаторазове) повернення, і кидок також повинен бути зведений до найнижчого мінімуму. Ніколи не хочеться бігти з середини петель гнізд. Ви завжди хочете, щоб у операторах управління циклом були всі керування циклом. Відступ має інформацію, і всі ці заяви викидають цю інформацію. Ви також можете вийняти всі відступи.


10
Ви хочете вирватися з циклу, якщо немає сенсу тримати виконання циклу. Інакше ви втратите більше часу на обробку в довших циклах без жодної причини.
Skuld

12
@ Кірк, це звучить як думка, а не що-небудь кількісне?
Брайан Скотт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.