简体   繁体   English

使用goto case(变量); 在C#开关

[英]Using goto case(variable); in C# switch

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). 我正在为Visual Studio C#控制台中的课程编写文本冒险,并决定使用switch语句而不是if-elses链,因为goto情况有多么有用(到目前为止它已经非常有效)。 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. 我知道交换机本身的每个案例都必须是一个常量,但我想知道这是否也延伸到使用goto情况。 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). 一切正常,但有一个“预期值不变”的警告(travel2A)。 Is it possible to make goto case input a variable with some tweaks or is that just a limitation of the switch statement? 是否可以通过一些调整使goto case输入变量,或者只是switch语句的限制? If it's the latter I can just do a chain of if-elses but imputting a variable is more convenient in my opinion. 如果是后者,我可以做一个if-elses链,但在我看来,输入变量更方便。 Any help on this is greatly appreciated! 非常感谢任何帮助! Thank you! 谢谢!

Labels for an ordinary goto are required to be spelled out in the source code. 普通goto标签需要在源代码中拼写出来。 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. goto case标签必须是常量表达式,在编译时评估,而不是在运行时评估。

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"; 对任何一种“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#经过精心设计,但最糟糕的“goto”滥用是不可能或不太可能的,但这种偏见确实存在一些真相。 (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".) (C#只允许在同一个块内或从内部块到其中一个包含块的getos。它永远不允许从外部块转到内部块,或者在两个没有嵌套关系的块之间。这大大降低了可能性“意大利面条代码”。)

I assume since you are taking a course you are just beginning to learn C#. 我假设你正在上一门课程,你才开始学习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. 虽然我们批评你的代码:考虑使用int.TryParse而不是Convert.ToInt32 ,并确保你处理用户键入非整数的情况。

See THIS POST 看到这个POST

Basically Switches cannot have evaluated statements in the case statement. 基本上,开关不能在case语句中包含evaluate语句。 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. 编译器错误A constant value is expected

The reason this is not possible in C# (VB Select operates slightly different) is well demonstrated when you run it in debug mode. 当您在调试模式下运行时,可以很好地演示在C#中无法实现这一点的原因(VB Select操作略有不同)。 Whenever you encounter a switch statement, you'll notice that the code will jump to the selected case. 每当遇到switch语句时,您都会注意到代码将跳转到所选的大小写。 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. 因此,不使用goto case(travel2a) ,而是使用可重新调用switch语句的方法调用。

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: 您可以将case代码组织为方法并简单地调用它:

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) {...}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM