简体   繁体   English

如何避免 C# while 和 do-while 循环中的代码重复?

[英]How can I avoid code duplication in C# while and do-while loops?

I have a loop inside a C# method that has the following structure.我在具有以下结构的 C# 方法中有一个循环。

do
{
     getUserInput();
     if (inputIsBad)
     {
          doSomethingElse();
     } 
} while (inputIsBad);

alternately, with a while loop:或者,使用 while 循环:

getUserInput();
while (inputIsBad)
{
     doSomethingElse();
     getUserInput();
}

But both methods use redundant code: the do-while has both an if statement and while loop checking the same condition;但是这两种方法都使用了冗余代码:do-while 有一个 if 语句和 while 循环检查相同的条件; the while loop calls getUserInput() both before and inside the loop. while 循环在循环之前和内部都调用 getUserInput()。

Is there a simple, non-redundant, non- ad hoc way to do what these method patterns do, either generally or in C# specifically, that only involves writing each basic component once?是否有一种简单的、非冗余的、非临时的方式来完成这些方法模式所做的事情,无论是一般情况下还是在 C# 中,只涉及编写每个基本组件一次?

Assuming that getUserInput(..) can be converted into a expression yielding a boolean value*..假设getUserInput(..)可以转换成一个表达式,产生一个布尔值*..

while (getUserInput()
    && isBadInput()) {
  doSomethingElse();
}

// Prompts for user input, returns false on a user-abort (^C)
private bool getUserInput() { .. }

Other variations (presumed without non-local state) shown in comments.注释中显示的其他变体(假定没有非本地状态)。

*Trivially, it can always be written as a wrapping function - see Local Functions , introduced in C#7. *简单地说,它总是可以写成一个包装函数 - 请参阅 C#7 中引入的本地函数 (There are other methods for the same effect, some of which I consider 'too clever'.) (还有其他方法可以达到相同的效果,我认为其中一些“太聪明了”。)

// local function
bool getUserInputAlwaysTrue() {
   getUserInput(); // assume void return
   return true;
}

while (getUserInputAlwaysTrue()
    && isBadInput()) {
  doSomethingElse();
}

This can be followed to pushing out the logic further, in some cases.在某些情况下,这可以用于进一步推出逻辑。 The general premise holds: getUserInput() is always invoked prior to the next isBadInput() .一般前提是: getUserInput()总是在下一个isBadInput()之前被调用。

// local function or member method
// Prompt for user input, returning true on bad input.
bool getCheckedUserInput() {
   getUserInput(); // assume void return
   return isBadInput();
}

while (getCheckedUserInput()) {
  doSomethingElse();
}
do
{
     getUserInput();

     if (!inputIsBad) break;

     doSomethingElse();

} while (true);

I would use a boolean variable, which you need to declare outside the body of the loop.我会使用一个布尔变量,你需要在循环体之外声明它。 That way you only need to run the inputIsBad check once.这样你只需要运行一次inputIsBad检查。 I have turned it into a method as well, since that seems more logical.我也把它变成了一种方法,因为这看起来更合乎逻辑。

bool badInput = true;  // Assume bad until checked -- failsafe.
do
{
  getUserInput();
  badInput = inputIsBad();
  if (badInput)
  {
    doSomethingElse();
  } 
} while (badInput);

Building on user2864740's answer:基于user2864740 的回答:

Assume getUserInput() can be converted into a function which returns true if the input is good and bad otherwise.假设 getUserInput() 可以转换为一个函数,如果输入是好的则返回 true,否则返回 true。 Assuming its original return type wasn't boolean or void, return its original return value via an out or ref parameter depending on the case, eg假设其原始返回类型不是布尔值或空值,则根据情况通过 out 或 ref 参数返回其原始返回值,例如

int originalReturnValue;

while (!getUserInput(out originalReturnValue))
{
     doSomethingElse();
} 

...

bool getUserInput<T>(out T output)
{
// method body
}

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

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