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;
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.
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.
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).
3.145.172.146