Introduction
There has been a lot of hysteria about the 'goto' statement since the famous 
computer scientist, Edsger Dijkstra, said in 1968 that he considered it to be 
"harmful".
In those days, he had a point because the 'goto' statement produced a lot of 
spaghetti code particularly by those using early versions of the BASIC 
programming language.
Despite this warning, 'goto' was included in C, C++ and C#. It wasn't included 
in Java though they do have labelled 'break' and 'continue' statements which 
achieve much the same thing.
In C#, it's much tamer than in some other languages as you can't jump into a 
nested block; you can only jump out of (or within) one. As far as the compiler 
is concerned, it works quickly because it can be mapped directly to CIL, and 
thence to native code, 'jump' instructions.
Although 'goto' isn't needed much in modern programming and it's always possible 
to program around it, I believe its use is acceptable in certain scenarios which 
I'd like to examine in this article. The scenarios presented are not necessarily 
exhaustive.
Jumping between 'case' blocks in a 'switch' statement 
Unlike C, C++ and Java, C# doesn't permit code to 'fall through' from one case 
block to another unless the first case block is empty. This eliminates some 
potentially hard to find bugs. If you do need to fall through, you can use the 
'goto case' construct instead:
string 
position = "first"; 
switch 
(position)
{
    case "first":
        DoSomething();
        goto case
"second"; // not allowed to 'fall through' 
here
    case "second":
        DoSomethingElse();
        break;
} 
This is nice and clean and I don't think many 
C# developers would quarrel with this usage.
Jumping out of (or within) deeply nested loops
The 'break' statement only jumps out of the current loop. If you want to exit 
from two or more nested loops, then the usual solution is to use bool variables 
in the following manner:
bool 
finished = false; 
for 
(int i = 0; i < 10; i++)
{
    while (someCondition)
    {
        //  ....
        if (someOtherCondition)
        {
            finished = true;
            break;
        }
    }
    if (finished) break;
}
Now, this is a reasonable solution when you 
only have two nested loops but, if you have more than this, then it can become 
unwieldy and error prone. In this situation, using 'goto' is much simpler and 
clearer:
for 
(int i = 0; i < 10; i++)
{
    for (int j = 
0; j < 10; j++)
    {
        while (someCondition)
        {
            //  ....
            if (someOtherCondition)
            {
                goto finished;
            }
        }
    }
}
 
finished:
// code following loops
Similar considerations apply to the 'continue' 
keyword which can only continue the current loop. If you want to continue an 
outer loop, then 'goto' can be used instead of bool variables:
for 
(int i = 0; i < 10; i++)
{
    for (int j = 
0; j < 10; j++)
    {
        while (someCondition)
        {
            //  ....
            if (someOtherCondition)
            {
                goto continuation;
            }
        }
    } 
   continuation: ; // empty statement here
}
Although having to jump to an empty statement 
is rather ugly, it's usually cleaner than the alternatives.
Retrying code after making corrections
The situation sometimes arises where you'd like to try a piece of code and, if 
it fails, make a correction and try it again. As C# lacks a 'retry' statement, 
you might come up with code such as this:
int 
x = 4, y = 0;
int 
z;
bool 
success;
 
do
{
    success = true;
 
    try
    {
        z = x / y;
    }
    catch (DivideByZeroException)
    {
        y = 2;
        success = false;
    }
 
} while (!success);
 
Console.WriteLine(z);
This works and isn't too bad but using 'goto' 
is cleaner and clearer:
int 
x = 4, y = 0;
int 
z;
 
retry:
try
{
    z = x / y;
}
catch 
(DivideByZeroException)
{
    y = 2;
    goto retry;
}
Console.WriteLine(z);
Conclusion
I should warn you now that prejudice against the 'goto' statement runs very deep 
and its use is often banned by some programming teams. However, I hope I've 
demonstrated that there are a few scenarios where its use may be beneficial so 
don't ignore it, if you have the choice!