Question

I know that goto is a bad DESIGN practice. But imagine we are stuck on a desert island, with nothing but gotos and ifs in our toolbox. Wouldn't then this:

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

be identical to this:

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

?

Isn't it true that you could do anything you normally could in c# using just using conditional logic, assigning/changing variables, method calls and jumps?

Was it helpful?

Solution

Technically? Yes, absolutely. Goto programs are turing complete and as such you can represent everything as them. In the end, machine code is pretty much similar to a goto program as loops and stuff are all done using conditional jumps. Of course in .NET you won’t be able to use only goto. At some point you will run into places where you either use other code which isn’t written like that, or you are at a location where the language structure forces you to do other stuff (make classes, methods, functions etc.). But technically, yes.

Should you do it however? Absolutely not. Goto programs are very hard to maintain, and as C# compiles into Intermediary Language, which uses jumps but on a higher level, you will probably lose a huge amount of performance when doing that. Also, the virtual machine can optimize a lot in “normal” code which it can’t when you put it in a fixed goto-schema.

Btw. your original code compiles into this IL, which is essentially what you wrote using goto (annotations by me):

// 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

OTHER TIPS

Yes, you could re-write any program to have the same output without using any loops. Method calls could all be inlined, so you don't technically need those either. Of course, classes and interfaces are not essential for any logic either. In fact, you could do just about everything with if, goto, assignment, and addition. Maybe you don't even need that much.

There is nothing necessarily inherently bad about goto. What makes it so that it should not be used are the following:

  • it is extremely easy to abuse, and takes great control to use properly; and even then it will tend to make code harder to read

  • it is always possible to use a more readable construct, like while, do, for, or foreach

Since it is simultaneously always possible and always better to use something else, there should never be any actual use of goto.

The one possible exception that I have heard of is breaking out of deep nesting:

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++)

And to answer your question more directly, yes it's completely possible to do all control flow with gotos rather than whiles, dos, etc... I might even suggest that would be a good challenge for practice, but not in any real code, and it would probably be a better learning experience to try coding in assembly rather than forcing yourself to use gotos.

Yes, it is possible. Ultimately, it's how assembly works. There is no such thing as loops in assembly. To change your location in the code, you have to use the equivalent of "goto" (usually jmp or some form of "branch") or a function call (if they exist).

However, if a code base I inherited used gotos, I'd either rewrite it from scratch or quit if I'm not allowed.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top