Question

I'm writing a text adventure for a course in the Visual Studio C# console, and decided to use the switch statement instead of a chain of if-elses due to how useful goto case can be (it has worked remarkably so far). I know that each case within the switch itself has to be a constant but I'm wondering if this extends to using goto case as well. For example I have:

switch (location)
{
case 1:
  break;
case 2:
  break;
case 3:
  break;
//I have 10 cases, each representing a location such as "Orc Cave", I just cut it down for brevity
default:
  break;
}

I would like to be able to input an integer variable and then go to that integer, I have the following to accomplish that:

string travel2 = Console.ReadLine();//inputs a integer representing each location
int travel2A = Convert.ToInt32(travel2);
if (1<=travel2A && travel2A<=10)
{
    goto case(travel2A);
}
else{
    goto case(2);//current location
}

Everything works fine yet there is a "A constant value is expected" warning underlinining the case(travel2A). Is it possible to make goto case input a variable with some tweaks or is that just a limitation of the switch statement? If it's the latter I can just do a chain of if-elses but imputting a variable is more convenient in my opinion. Any help on this is greatly appreciated! Thank you!

Was it helpful?

Solution

Labels for an ordinary goto are required to be spelled out in the source code. They are not expressions that are evaluated; they are simply identifiers. Labels for goto case are required to be constant expressions, evaluated at compile time, not at run time.

I would caution you against any solution that relies heavily on "goto" of any form. There is a popular prejudice against any kind of "goto"; gotos are believed to be inelegant and make your code hard to follow. There is some truth underlying this prejudice to be sure, though C# has been carefully designed so that the worst abuses of "goto" are impossible or unlikely. (C# only allows gotos within the same block or from an inner block to one of its containing blocks. It never allows a goto from an outer block into an inner block, or between two blocks that have no nesting relationship. This greatly reduces the likelihood of "spaghetti code".)

I assume since you are taking a course you are just beginning to learn C#. As you advance you'll learn about control flow techniques that are more elegant than switching on cases.

While we are criticizing your code: consider using int.TryParse rather than Convert.ToInt32, and make sure you handle the case where the user types in something that is not an integer.

OTHER TIPS

See THIS POST

Basically Switches cannot have evaluated statements in the case statement. They must be statically evaluated.

How about:

int travel2A = Convert.ToInt32(travel2);
if( travel2A < 1 || travel2A > 10 )
    travel2A = 2;

switch( travel2A ) { ... }

The compiler error A constant value is expected says it all.

The reason this is not possible in C# (VB Select operates slightly different) is well demonstrated when you run it in debug mode. Whenever you encounter a switch statement, you'll notice that the code will jump to the selected case. While you gain a significant performance boost by skipping several compares, it limits the flexiblity.

One way I've gotten around this in the past is recursion with anonomous methods. So instead of using goto case(travel2a), you would use a method call that would re-call the switch statement.

Action<int> foo = null;
foo = (i) =>
{
    switch (i)
    {
        case 1:
            Console.WriteLine("1");
            break;
        case 2:
            Console.WriteLine("1");
            break;
        case 3:
            Console.WriteLine("1");
            break;
        default:
            //goto case (i%3);
            foo(i % 3);
            break;
    }
};

foo(4);

You can organize case code as a method and simply call it:

switch (location)
{
    case 1:
        gocave();
        break;
    case 2:
        gocave();
        break;
    case 3:
        donotgocave();
        break;
}

or split complicated logic into primitives:

bool gocave = false;
bool eatmushroom = false;
switch (location)
{
    case 1:
        gocave = true;
        break;
    case 2:
        gocave = true;
        eathmushroom = true;
        break;
    case 3:
        break;
}
if(gocave) {...}
if(eatmushroom) {...}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top