我有一个完全正常运行的程序,我现在正在重构它。我正处于学习c#的过程中,所以原始代码非常糟糕,尽管它运行得很好。该程序的要求之一是用户可以随时返回主菜单。我完成了如下:
static bool bouncer = false
static void Exit(string input)
{
if (input == "\t")
{
bouncer = true
}
}
static string Prompt(string msg)
{
// takes input and passes it to Exit() then returns the input
}
static string FunctionA()
{
while(true)
{
if (bouncer == true)
{
break;
}
Prompt("whatever")
if (bouncer == true)
{
break;
}
Prompt("whatever")
if (bouncer == true)
{
break;
}
// return some stuff
}
}
static void Main()
{
bouncer = false
// writes the menu to console and handles UI
// FunctionA
{
如果用户在任何输入点输入“tab”字符,变量bouncer将设置为true。 break语句条件的增加提供了实际分解回Main()的结构。这显然不是一个很好的解决方案,它使代码难以阅读。
我认为完成相同任务的其他尝试是:
Goto语句直接跳回Main()。我之所以废弃这个,是因为goto在c#中的范围非常有限,我认为在这种情况下没有任何好办法让它可行。
直接从Exit()调用Main()。这可能是一个坏主意,我无论如何都做不到,因为显然Main()在某种程度上受到“保护”。
使用事件对TAB或ESC进行反应。我不清楚如何使用一个事件来做这件事,因为我仍然无法突破事件。我的理解是break语句实际上必须包含在需要被打破的循环中,而不是被写入从循环中调用的不同函数。
非常感谢任何建议。我希望事件处理能够做些什么,或者我忽略了一些更简单的事情。谢谢!
答案 0 :(得分:1)
而不是无限循环和break语句,请尝试使用条件标志。
static void FunctionA()
{
bool done = false;
string response = string.Empty;
while (!done)
{
response = Prompt("whatever");
if(response == '\t')
{
done = true;
}
}
}
作为旁注,我不确定为什么你有'字符串'作为几种方法的返回类型(例如,' FunctionA'),当您没有使用返回值时。这就是为什么我上面给出的代码将其作为' void'。
答案 1 :(得分:1)
作为编码风格的问题,它的工作方式,但被视为丑陋。不幸的是,如果你需要在各个工作部分之间立即突破,那么就没有很多办法了。
您可以使用“static string FunctionA()
{
bool bContinue = true;
while( true == bContinue )
{
// Do initital work.
//
// Initial work can set bContinue to false if any error condition
// occurs.
if( true == bContinue )
{
// Do more work.
int returnCheck = MakeACall(); // Presume MakeACall returns negative interger values for error, 0 or positive values for success or success with condition/extra information.
if( 0 < returnCheck )
{
bContinue = false;
}
}
if( true == bContinue )
{
Prompt("whatever")
// Do more work.
bContinue = MakeASecondCall(); // Presume that MakeASecondCall returns true for success, false for error/failure
}
if( true == bContinue )
{
Prompt("whatever")
// Do more work.
// If error encountered, set bContinue to false.
}
if( true == bContinue )
{
Prompt("whatever else")
// Do more work.
// If error encountered, set bContinue to false.
}
// Done with loop, so drop out.
bContinue = false;
// return some stuff
}
}
”控件样式更改当前使用中断的格式。它将代码从while循环中删除到:
Do-While(false)
查看您的伪代码,它看起来就像您只通过工作循环一次。如果是这样,您可以切换到FunctionA
格式,并使用中断放到底部。或者,如果您只是通过While
进行一次传递,则只需取消使用Do-While
或if(true==bContinue){ /* Do more work */ }
控件结构,然后使用while
。它不是最干净的代码,但是当你执行长时间的连续工作时,如果你不打算使用do-while
或if(bContinue){}
来控制流程,你最终会得到这样的结构。
使用break
样式的缺点是,在进程的早期阶段发生错误情况时,代码不会像while()
那样快速退出函数。如果错误发生在工作顶部附近,则do-while()
或if
结构,因为代码将测试然后跳过一系列nContinue
语句。但它是可读的,如果你为你的控制变量使用一个描述性名称(即bContinue
或workLoopControl
或timer
),那么很明显它是主控制标志函数的工作流程是在你之后工作或审查代码的人。