2013-09-29 2 views
2

Я знаю, что goto - плохая практика DESIGN. Но представьте себе, что мы застряли на необитаемом острове, с ничего, кроме gotos и ifs в нашей панели инструментов. Не то это бы:Возможно ли сделать все с помощью goto's?

int i = 0; 
    while (i < 10) i++; 

быть идентичным образом:

int i = 0; 
    loop: if (i < 10) { i++; goto loop; } 

?

Не правда ли, что вы могли делать что-либо, что обычно было в C#, используя только условную логику, назначение/изменение переменных, вызовы методов и переходы?

+2

no. если бы программирование было таким, что я предпочел бы оставить свою работу и быть бездомным нищим –

+1

@HighCore It _is_ возможно. Как работает сборка. Это _practical_? № –

+0

@colejohnson справа. Моя точка все еще стоит, хотя –

ответ

4

Технически? Да, конечно. Программы Goto завершаются и, таким образом, вы можете представлять все как они. В конце концов, машинный код в значительной степени похож на программу goto, поскольку циклы и все это делается с помощью условных переходов. Конечно, в .NET вы не сможете использовать только goto. В какой-то момент вы столкнетесь с местами, в которых вы либо используете другой код, который не написан подобным образом, либо вы находитесь в том месте, где языковая структура заставляет вас делать другие вещи (создавать классы, методы, функции и т. Д.). Но технически, да.

Должны ли вы это сделать? Точно нет. Программы Goto очень сложно поддерживать, а поскольку C# компилируется в язык посредника, который использует переходы, но на более высоком уровне, вы, вероятно, потеряете огромную производительность при этом. Кроме того, виртуальная машина может много оптимизировать в «нормальном» коде, который он не может, когда вы помещаете его в фиксированную схему goto.

КПП. исходный код компилируется в этот IL, который, по существу, что вы написали с помощью Гото (аннотаций мной):

// i = 0 
IL_0001: ldc.i4.0     // Load integer value 0 to stack 
IL_0002: stloc.0 // i   // Store stack value in local variable 0 

// goto loop-condition 
IL_0003: br.s  IL_0009   // Jump to IL_0009 

// loop-start: 
// i = i + 1 
IL_0005: ldloc.0 // i   // Load variable 0 to stack 
IL_0006: ldc.i4.1     // Load integer `1` to stack 
IL_0007: add      // Add top two stack values 
IL_0008: stloc.0 // i   // Store result in local variable 0 

// loop-condition: 
// if (i < 10) { goto loop-start } 
IL_0009: ldloc.0 // i   // Load variable 0 to stack 
IL_000A: ldc.i4.s 0A    // Load integer `10` to stack 
IL_000C: clt      // Compare top two stack values 
IL_000E: stloc.1 // CS$4$0000 // Store stack value in local variable 1 
IL_000F: ldloc.1 // CS$4$0000 // Load variable 1 to stack 
IL_0010: brtrue.s IL_0005   // Jump to IL_0005 if stack value is true 
+0

Если вы ограничились эмуляцией стандартных структур управления с gotos (в отличие от прыжков в стиле спагетти), то код будет не сложнее поддерживать, чем код с надлежащими структурами управления. –

4

Да, вы можете перезаписать любую программу для получения того же выхода без использования каких-либо петель. Все вызовы методов могут быть встроены, так что вам это тоже не требуется. Разумеется, классы и интерфейсы не являются существенными для любой логики. Фактически, вы могли бы сделать почти все с if, goto, присваиванием и добавлением. Может быть, тебе даже этого не нужно.

1

Да, это возможно. В конечном итоге, как работает сборка. В сборке нет таких элементов, как петли. Чтобы изменить свое местоположение в коде, вы должны использовать эквивалент «goto» (обычно jmp или какой-либо форме «ветки») или вызов функции (если они существуют).

Однако если код, который я унаследовал, использовал goto s, я бы переписал его с нуля или ушел, если мне не разрешат.

4

Там нет ничего обязательно по своей природе плохо goto.Что делает это так, что она не должна использоваться следующие:

  • это чрезвычайно легко злоупотребить, и занимает большой контроль, чтобы использовать должным образом; и даже тогда он будет стремиться сделать код труднее читать

  • это всегда можно использовать более читаемую конструкцию, как while, do, for или foreach

С ней всегда всегда возможно и всегда лучше использовать что-то другое, никогда не должно быть никакого фактического использования goto.

Возможным исключением, что я слышал о вспыхивают глубокой вложенности:

for (int x = 0; x < 100; x++) 
    for (int y = 0; y < 100; y++) 
     for (int z = 0; z < 100; z++) 
     if (condition) 
      goto end; 
end: ; 

VS

for (int x = 0; x < 100, !condition; x++) 
    for (int y = 0; y < 100, !condition; y++) 
     for (int z = 0; z < 100, !condition; z++) 

И ответить на ваш вопрос более непосредственно, да, это вполне возможно сделать все управляющий поток с goto s, а не while s, do s и т. д. Я мог бы даже предположить, что это был бы хороший вызов для практики, но не в каком-либо реальном коде, и, вероятно, это было бы лучше, чтобы попытаться кодировать в сборке, а не заставлять себя использовать goto.

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