3

我正在为 Visual Studio C# 控制台中的一门课程编写文本冒险,并决定使用 switch 语句而不是 if-else 链,因为 goto 案例非常有用(到目前为止它工作得非常好)。我知道开关本身中的每个案例都必须是一个常数,但我想知道这是否也扩展到使用 goto 案例。例如我有:

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;
}

我希望能够输入一个整数变量,然后转到该整数,我有以下内容来完成:

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
}

一切正常,但在案例(travel2A)的下方有一个“预期值为常数”的警告。是否可以通过一些调整使 goto case 输入变量,或者这只是 switch 语句的限制?如果是后者,我可以执行一系列 if-else,但在我看来,输入变量更方便。非常感谢您对此的任何帮助!谢谢!

4

5 回答 5

7

普通goto的标签需要在源代码中拼写出来。它们不是被评估的表达式;它们只是标识符。for 的标签goto case必须是常量表达式,在编译时计算,而不是在运行时计算。

我会提醒您不要使用任何严重依赖任何形式的“goto”的解决方案。对任何一种“goto”都有一种普遍的偏见。gotos 被认为是不优雅的并且使您的代码难以遵循。可以肯定的是,这种偏见背后有一些真相,尽管 C# 已经过精心设计,因此“goto”的最严重滥用是不可能或不可能的。(C# 只允许 goto 在同一个块内或从内部块到其包含块之一。它从不允许从外部块到内部块,或在没有嵌套关系的两个块之间。这大大降低了可能性“意大利面条代码”。)

我假设由于您正在学习课程,因此您才刚刚开始学习 C#。随着您的进步,您将了解比打开案例更优雅的控制流技术。

当我们批评您的代码时:考虑使用int.TryParse而不是Convert.ToInt32,并确保您处理用户键入的内容不是整数的情况。

于 2013-10-10T15:28:14.460 回答
2

见这篇文章

基本上 Switch 不能在 case 语句中包含评估语句。必须对它们进行静态评估。

于 2013-10-10T15:25:25.627 回答
0

怎么样:

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

switch( travel2A ) { ... }
于 2013-10-10T15:31:47.543 回答
0

编译器错误A constant value is expected说明了一切。

当您在调试模式下运行它时,这在 C# 中不可能(VBSelect操作略有不同)得到了很好的证明。每当您遇到switch语句时,您会注意到代码将跳转到选定的案例。虽然您通过跳过多次比较获得了显着的性能提升,但它限制了灵活性。

我过去解决这个问题的一种方法是使用匿名方法进行递归。因此goto case(travel2a),您将使用重新调用switch语句的方法调用,而不是 using 。

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);
于 2013-10-10T15:37:50.733 回答
-2

您可以将case代码组织为方法并简单地调用它:

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

或将复杂的逻辑拆分为原语:

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) {...}
于 2013-10-10T15:48:19.473 回答