11.6. Flow control with the goto keyword

Yes, goto is still there in C#, although the makers of Java got rid of its functionality (still reserving the goto keyword) when they designed Java from C++. Nevertheless, do you realize that if you have been using labels in Java, and break-ing or continue-ing to such labels, you are actually performing a pseudo goto (without the goto keyword)?

There are three ways to use C#'s goto:

  • goto case <expression>;

  • goto <label>;

  • goto default;

11.6.1. Using goto in switch-case blocks

goto can be quite useful in switch-case blocks too, since 'falling-through' case blocks is no longer supported in C#.

Their use should be clear from this example (see section 11.4):

 1:  using System;
 2:
 3:  class TestClass{
 4:    public static void Main(){
 5:      int i = 1;
 6:
 7:      switch(i){
 8:            case 1 : Console.WriteLine("ONE");
 9:                     goto case 3;
10:
11:            case 2 : Console.WriteLine("TWO");
12:                     break;
13:
14:            case 3 : Console.WriteLine("THREE");
15:                     goto default;
16:
17:            default : Console.WriteLine("DEFAULT");
18:                      break;
19:      }
20:    }
21:  }

Output:

c:expt>test
ONE
THREE
DEFAULT

Study line 9 which shows how the goto case expression is used to force both the case 1 and case 3 blocks to be executed in the event when i==1.

11.6.2. Using goto <label>

If you use labels in Java, you can use the break and continue statements to force execution flow to continue from a particular label. C#'s break and continue keywords do not take in a label – you use C#'s goto <label> to exit an outer loop from an inner loop prematurely. Instead of labeling the loop (which you do in Java), you label a statement outside the loop you want to break out of, and goto that statement.

Study this example:

 1:  using System;
 2:
 3:  class TestClass{
 4:    public static void Main(){
 5:
 6:      for (int i=0; i<5; i++){
 7:        for (int j=0; j<5; j++){
 8:          Console.WriteLine(i+","+j);
 9:          if (j==3)
10:            goto End;
11:        }
12:        Console.WriteLine("skipped");
13:      }
14:
15:      End: // arbitrary label
16:        Console.WriteLine("end");
17:    }
18:  }

Output:

c:expt>test
0,0
0,1
0,2
0,3
end

Because of the goto End; statement on line 10, line 12 will never get to execute since the inner for loop never completes.

However, the following code does not compile:

 1:  using System;
 2:
 3:  class TestClass{
 4:
 5:    public static void Main(){
 6:
 7:      goto InsideLoop;
 8:      for (int i=0; i<5; i++){
 9:        InsideLoop:
10:          Console.WriteLine("looping");
11:      }
12:    }
13:  }

Compilation warnings and error:

test.cs(8,5): warning CS0162: Unreachable code detected
test.cs(7,5): error CS0159: No such label 'InsideLoop' within the scope of the goto statement
test.cs(9,7): warning CS0162: Unreachable code detected
test.cs(9,7): warning CS0164: This label has not been referenced

Line 8 is unreachable, and the compiler generates a warning (not an error though). The error thrown by the compiler is what I want to draw your attention to – 'InsideLoop' is not within the scope of the goto statement, since it is in a for loop. You can jump from inside a loop to outside, but not from outside to inside. [7] Even if you shift line 7 to between lines 11 and 12, you will still get the same compilation error.

[7] Wouldn't it be messy if you could jump right into the middle of a loop? Obvious ambiguities include deciding which iteration it will be. It's for that reason that you are not allowed to hop into a statement in the middle of a loop using goto <label>.

If a label is specified but not used, the compiler will give a warning that the label has not been referenced. In the code example above, if line 7 is deleted but the label of line 9 is kept, the class compiles with a compilation warning, but runs fine.

11.6.3. Misusing the goto keyword

Although you can jump around blocks of code using labels and the goto <label> statement, you should restrict its use to breaking out from inner loops.

Here's an example of how the goto <label> statement can be legally abused.

 1:  using System;
 2:
 3:  class TestClass{
 4:
 5:    public static void Main(){
 6:
 7:      Label1:
 8:        Console.WriteLine("never ");
 9:        goto Label2;
10:
11:      Label2:
12:        Console.WriteLine("ending ");
13:        goto Label1;
14:    }
15:  }

Output:

c:expt>test
never
ending
never
ending
never
ending
never
ending
never
ending

(etc )

The output has been truncated. It carries on printing 'never' and 'ending' on alternate lines until you force a termination (by hitting Ctrl-C if running from the command line).

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.14.134.17