Difference between GOTO and DO WHILE

Are there any differences between the two C # snippets below?

do
{
    Console.WriteLine(x.ToString());
    ++x;
} 
while (x < 7);

      

and

label:
{
    Console.WriteLine(x.ToString());
    ++x;
}
if (x < 7) goto label;

      

I'm trying to figure out why it's so bad. Thank.

EDIT: If I add parentheses, the fragments are pretty similar.

EDIT2: In Visual Studio, I clicked the Go to Disassemble button and got the following code:

            do
            {
00000037  nop 
                Console.WriteLine(x.ToString());
00000038  lea         ecx,[ebp-40h] 
0000003b  call        63129C98 
00000040  mov         dword ptr [ebp-48h],eax 
00000043  mov         ecx,dword ptr [ebp-48h] 
00000046  call        63148168 
0000004b  nop 
                ++x;
0000004c  inc         dword ptr [ebp-40h] 
            } 
0000004f  nop 
            while (x < 7);
00000050  cmp         dword ptr [ebp-40h],7 
00000054  setl        al 
00000057  movzx       eax,al 
0000005a  mov         dword ptr [ebp-44h],eax 
0000005d  cmp         dword ptr [ebp-44h],0 
00000061  jne         00000037 

      

and

            label:
            {
                Console.WriteLine(x.ToString());
00000069  lea         ecx,[ebp-40h] 
0000006c  call        63129C98 
00000071  mov         dword ptr [ebp-4Ch],eax 
00000074  mov         ecx,dword ptr [ebp-4Ch] 
00000077  call        63148168 
0000007c  nop 
                ++x;
0000007d  inc         dword ptr [ebp-40h] 
            }
00000080  nop 
            if (x < 7) goto label;
00000081  cmp         dword ptr [ebp-40h],7 
00000085  setge       al 
00000088  movzx       eax,al 
0000008b  mov         dword ptr [ebp-44h],eax 
0000008e  cmp         dword ptr [ebp-44h],0 
00000092  jne         00000097 
00000094  nop 
00000095  jmp         00000068

      

The difference is an unconditional jump.

+3


source to share


2 answers


No, I even think that it is while

implemented as in the back.

The bad goto

thing to use is that it encourages back and forth through your code (also known by the term "spaghetti code": it's a mess). This makes your code extremely difficult to read, debug, and analyze, and it introduces errors as you can't figure out what's going on.



The good thing with while

is that you can understand it and the compiler can understand it, so it can give you good warnings.

+9


source


Let's take a look at IL:

.method private hidebysig 
    instance void While () cil managed 
{
    // Method begins at RVA 0x2050
    // Code size 31 (0x1f)
    .maxstack 2
    .locals init (
        [0] int32 x,
        [1] bool CS$4$0000
    )

    IL_0000: nop
    IL_0001: ldc.i4.0
    IL_0002: stloc.0
    // loop start (head: IL_0003)
        IL_0003: nop
        IL_0004: ldloca.s x
        IL_0006: call instance string [mscorlib]System.Int32::ToString()
        IL_000b: call void [mscorlib]System.Console::WriteLine(string)
        IL_0010: nop
        IL_0011: ldloc.0
        IL_0012: ldc.i4.1
        IL_0013: add
        IL_0014: stloc.0
        IL_0015: nop
        IL_0016: ldloc.0
        IL_0017: ldc.i4.7
        IL_0018: clt
        IL_001a: stloc.1
        IL_001b: ldloc.1
        IL_001c: brtrue.s IL_0003
    // end loop
    IL_001e: ret
} // end of method Program::While

.method private hidebysig 
    instance void Goto () cil managed 
{
    // Method begins at RVA 0x207c
    // Code size 34 (0x22)
    .maxstack 2
    .locals init (
        [0] int32 x,
        [1] bool CS$4$0000
    )

    IL_0000: nop
    IL_0001: ldc.i4.0
    IL_0002: stloc.0
    // loop start (head: IL_0003)
        IL_0003: ldloca.s x
        IL_0005: call instance string [mscorlib]System.Int32::ToString()
        IL_000a: call void [mscorlib]System.Console::WriteLine(string)
        IL_000f: nop
        IL_0010: ldloc.0
        IL_0011: ldc.i4.1
        IL_0012: add
        IL_0013: stloc.0
        IL_0014: ldloc.0
        IL_0015: ldc.i4.7
        IL_0016: clt
        IL_0018: ldc.i4.0
        IL_0019: ceq
        IL_001b: stloc.1
        IL_001c: ldloc.1
        IL_001d: brtrue.s IL_0021

        IL_001f: br.s IL_0003
    // end loop

    IL_0021: ret
} // end of method Program::Goto

      

The ILSpy event marks goto as a loop. When decompiling it to C #, it even shows both loops as do while

.

But there is more! The while loop has a scope:



        int x = 0;
        do
        {
            string z = "TEST";
            Console.WriteLine(x.ToString());
            ++x;
        }
        while (x < 7);
        Console.WriteLine(z); // invalid!

      

but this is true:

        int x = 0;
    label:
        string z = "TEST";
        Console.WriteLine(x.ToString());
        ++x;
        if (x < 7) goto label;
        Console.WriteLine(z);

      

Should you use it? Not! Check out Patricks .

+2


source







All Articles