使用goto案例(变量);在C#开关中
我正在Visual Studio C#console中为一门课程编写一篇文本冒险,并决定使用switch语句而不是if-else链,因为goto case非常有用(到目前为止它已经非常有效)。我知道开关本身中的每种情况都必须是常数,但我想知道这是否也扩展到使用goto情况。例如,我有:使用goto案例(变量);在C#开关中,c#,switch-statement,goto,C#,Switch Statement,Goto,我正在Visual Studio C#console中为一门课程编写一篇文本冒险,并决定使用switch语句而不是if-else链,因为goto case非常有用(到目前为止它已经非常有效)。我知道开关本身中的每种情况都必须是常数,但我想知道这是否也扩展到使用goto情况。例如,我有: switch (location) { case 1: break; case 2: break; case 3: break; //I have 10 cases, each representin
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
}
string travel2=Console.ReadLine()//输入一个表示每个位置的整数
int travel2A=转换为32(travel2);
如果(1见此
基本上,开关不能在case语句中有求值语句。它们必须进行静态求值。普通的goto
标签需要在源代码中拼写出来。它们不是求值的表达式;它们只是标识符。goto case
标签需要是常量xpressions,在编译时计算,而不是在运行时
我要提醒你,任何严重依赖任何形式的“goto”的解决方案都是不可取的。对任何形式的“goto”都存在普遍的偏见;goto被认为是不雅观的,并且使你的代码难以遵循。尽管C#经过精心设计,使得最恶劣的“goto”滥用行为成为可能,但这种偏见背后确实存在一些事实不可能或不太可能。(C#只允许在同一块内或从内部块转到其包含的块之一。它从不允许从外部块转到内部块,或在没有嵌套关系的两个块之间。这大大降低了“意大利面代码”的可能性。)
我想,既然你正在学习一门课程,你就刚刚开始学习C#。随着你的进步,你将学习到比打开案例更优雅的控制流技术
当我们批评您的代码时:考虑使用<代码> In .TyPARSE < /C> >而不是<代码> Real.ToTut32 ,并确保您处理用户键入不是整数的情况。
如何:
int travel2A = Convert.ToInt32(travel2);
if( travel2A < 1 || travel2A > 10 )
travel2A = 2;
switch( travel2A ) { ... }
inttravel2a=Convert.ToInt32(travel2);
如果(travel2A<1 | | travel2A>10)
travel2A=2;
开关(travel2A){…}
编译器错误需要一个常量值
说明了一切
这在C#中不可能实现的原因(VBSelect
操作略有不同)当您在调试模式下运行它时,它会得到很好的演示。每当您遇到switch
语句时,您都会注意到代码将跳转到所选的情况。虽然您通过跳过几个比较来获得显著的性能提升,但它限制了灵活性
过去我解决这个问题的一种方法是使用非规则方法进行递归。因此,不要使用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);
操作foo=null;
foo=(i)=>
{
开关(一)
{
案例1:
控制台。写入线(“1”);
打破
案例2:
控制台。写入线(“1”);
打破
案例3:
控制台。写入线(“1”);
打破
违约:
//后藤病例(i%3);
foo(i%3);
打破
}
};
foo(4);
您可以将案例
代码组织为一种方法,并简单地称之为:
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) {...}
如果您在开关
内,则只能转到案例
,而您不在第二个示例中。您没有标签“2”已定义。请参阅,然后立即查看并停止使用goto
。仅仅因为不能使用goto
,并不意味着不能使用switch
语句来实现此设计。请参阅我的答案以了解解决方法。您提到了对C的陌生。我建议,一旦您的代码正常工作,您可以尝试将其发布到以进行构造有意思的批评。谢谢!这只是我在C#的第二周,所以我还在熟悉它。我将切换到if else for traveling。谢谢你的int.TryParse推荐。我会马上做。@RussellDahlke:不客气。听起来你在思考控制流方面做得不错。现在退一步问问你自己如果你能更抽象地概念化你的流程。文本冒险游戏基本上是一个状态机。状态机有以下流程:(1)创建开始状态,(2)获取输入,(3)计算出当前状态和输入对状态的更改,(4)如果新状态是停止状态,则结束程序,(5)转到2。如果你能像这样组织你的程序,它可能更容易理解。显然(3)是困难的部分!