0

Is there performance impact of GOTO statement in c# code, instead of using loop or multiple separate user defined functions.

I am not sure but memory jump may occur with GOTO statement and can impact performance.

BrainCoder
  • 5,197
  • 5
  • 30
  • 33
  • Performance impact or not, it will literally ruin your maintainability. Never use `GOTO`s, unless you're stuck in a really specific niche problem without any alternatives. – Pierre-Luc Pineault Nov 25 '14 at 07:33
  • 1
    What performance difference did you find when you tried using `goto`? You did try it, right? I'm not as convinced as Pierre-Luc that simply using a `goto` means ruining your maintainability. And of course, it's a mandatory way to write fall-through `case` blocks. On the other hand, for flow control a `goto` does leave a lot to be desired, and pretty much always can be avoided. So you might as well; even if maintainability isn't ruined by a `goto`, it definitely gets a bit tarnished. :) – Peter Duniho Nov 25 '14 at 07:44
  • @PeterDuniho Methods are made to enhance readability. Classic `for` and `while` loops are easily distinguishable and easy to read. `GOTO`s can only make a huge mess, going all the way against basic OOP principles, SRP and will skyrocket your cyclomatic complexity through the roof while preventing any testability. I dare you to try to understand a 5k lines method with gotos in exactly the same time than a clean and structured OOP architecture. And honestly if you're trying to micro-optimize stuff like loops and methods (surely for absolutely no gain), just move to assembly already. – Pierre-Luc Pineault Nov 25 '14 at 07:50
  • @Pierre-LucPineault: who said anything about a method with five thousand lines? Give me a break...just because `goto` statements can be part of code that is otherwise also awful, that's no reason to believe that one `goto` statement in your code is literally going to ruin that code. – Peter Duniho Nov 25 '14 at 07:52
  • @Peter He talked about using GOTOs instead of methods. If the program makes 5k lines, that means you have a 5k lines single method. And we're not talking about one goto here (even if it's dangerous enough already), but replacing all the loops with em. – Pierre-Luc Pineault Nov 25 '14 at 07:59
  • @Pieree-LucPineault: you are right i have legacy code with 6K lines having multiple `goto` statements i am avoiding as much as possible with `loops` but some are unavoidable. – BrainCoder Nov 25 '14 at 10:48
  • @Pierre-LucPineault: I'm amazed that you feel it's reasonable to infer all that from the question as posted, considering no such specifics at all are included. In any case, your statement to which I was referring (barely as an aside at that) was far more broad than that, implying that _any_ use of even a single `goto` would be disastrous. An idea that clearly is just not true. – Peter Duniho Nov 25 '14 at 19:02
  • One rare place where GOTOs are the clearest expression is to implement state transitions. – user3344003 Nov 26 '14 at 03:43

1 Answers1

3

No, it doesn't.

It's hard to answer "does it impact peformance" without knowing what the alternative is but I'll make up a sample:

using System;
public class C {
    public void M() {
        var x = 7;
        switch(x) // START SWITCH
        {
            case 1:
                Console.WriteLine("Hello");
                break;
            case 2:
                Console.WriteLine("World");
                break;
            default:
                Console.WriteLine("Uh...");
                break;
        }
        // END SWITCH
        // START GOTO
        if (x == 1)
        {
            goto Hello;
        }
        else if (x == 2)
        {
            goto World;
        }
        Console.WriteLine("Uh...");
        goto End;
    Hello:
        Console.WriteLine("Hello");
        goto End;
    World:
        Console.WriteLine("World");
    End:
        // END GOTO
        Console.WriteLine("Done");
    }
}

Compiling this with C# in release mode (using sharplab.io default 2.9.0) yields the following IL (i.e. bytecode for you Java folk):

.class private auto ansi '<Module>'
{
} // end of class <Module>

.class public auto ansi beforefieldinit C
    extends [mscorlib]System.Object
{
    // Methods
    .method public hidebysig 
        instance void M () cil managed 
    {
        // Method begins at RVA 0x2050
        // Code size 99 (0x63)
        .maxstack 2
        .locals init (
            [0] int32
        )

        IL_0000: ldc.i4.7
        IL_0001: stloc.0
        // START SWITCH
        IL_0002: ldloc.0
        IL_0003: ldc.i4.1
        IL_0004: beq.s IL_000c

        IL_0006: ldloc.0
        IL_0007: ldc.i4.2
        IL_0008: beq.s IL_0018

        IL_000a: br.s IL_0024

        IL_000c: ldstr "Hello"
        IL_0011: call void [mscorlib]System.Console::WriteLine(string)
        IL_0016: br.s IL_002e

        IL_0018: ldstr "World"
        IL_001d: call void [mscorlib]System.Console::WriteLine(string)
        IL_0022: br.s IL_002e

        IL_0024: ldstr "Uh..."
        IL_0029: call void [mscorlib]System.Console::WriteLine(string)
        // END SWITCH
        // START GOTO
        IL_002e: ldloc.0
        IL_002f: ldc.i4.1
        IL_0030: beq.s IL_0042

        IL_0032: ldloc.0
        IL_0033: ldc.i4.2
        IL_0034: beq.s IL_004e

        IL_0036: ldstr "Uh..."
        IL_003b: call void [mscorlib]System.Console::WriteLine(string)
        IL_0040: br.s IL_0058

        IL_0042: ldstr "Hello"
        IL_0047: call void [mscorlib]System.Console::WriteLine(string)
        IL_004c: br.s IL_0058

        IL_004e: ldstr "World"
        IL_0053: call void [mscorlib]System.Console::WriteLine(string)
        // END GOTO
        IL_0058: ldstr "Done"
        IL_005d: call void [mscorlib]System.Console::WriteLine(string)
        IL_0062: ret
    } // end of method C::M

    .method public hidebysig specialname rtspecialname 
        instance void .ctor () cil managed 
    {
        // Method begins at RVA 0x20bf
        // Code size 7 (0x7)
        .maxstack 8

        IL_0000: ldarg.0
        IL_0001: call instance void [mscorlib]System.Object::.ctor()
        IL_0006: ret
    } // end of method C::.ctor

} // end of class C

The switch form has 3 beq and 1 br.s and the goto form has 2 beq and 2 br.s, other than that they are identical. The cost of br.s is presumably less than or equal to the cost of beq so the cost of the goto approach is not greater than the cost of the switch approach.

Finally, using goto is a bad idea. If you want to argue about that fact please do so on a different question like this one: What is wrong with using goto?

Pace
  • 41,875
  • 13
  • 113
  • 156