while-loop with break而不是while(condition)

时间:2013-12-26 18:53:21

标签: c# loops

好的 - 所以也许我累了,但我正在尝试找到一种方法来做以下事情(一个似乎......更优雅?)

  • 我有一个布尔值(我们称之为loopTwice
  • loopTwice由循环内容使用(并修改其行为)以执行互斥功能
  • 如果loopTwice为真,我希望循环执行两次,首先使用值true,然后使用值false
  • 如果loopTwice为false,我希望循环只执行一次,值为false
  • 循环后不使用
  • loopTwice,因此最终值
  • 无关紧要

...这似乎有足够的意义,但出于某种原因,我的大脑没有提出任何比一个有一个if条件的while循环更优雅的东西休息:

// loopTwice is already set as true or false
while (true) //this seems ugly, not to mention breakable...
{
    DoThis(loopTwice);          //these act slightly differently based upon loopTwice
    DoThat(loopTwice);          //these act slightly differently based upon loopTwice
    DoAnotherThing(loopTwice);  //these act slightly differently based upon loopTwice

    if (!loopTwice) break;
    loopTwice = false;
}

这段代码(好吧,不是这段代码,而是等效的代码......)完全按照我的意愿工作而没有配置另一个变量(我猜这不是一件坏事,但我没有看到使用另一个变量制作任何比这更优雅的循环......)

在我看来,必须有一些我缺少的东西(一种方法可以循环两次,如果某些东西是真的,一次如果某些东西是假的,“假”值总是最后的 - 并且最好没有第二个变量,比如一个计数器或第二个标志,表示循环已经运行一次。)

使用计数器或旗帜实际上更优雅吗? (我想在过去几十年的计算机中,它并没有真正冒险破坏内存要求或任何东西,是吗......)。将此分解为函数并使用递归会更优雅吗?嗯...

当然,优雅是在旁观者的眼中......

6 个答案:

答案 0 :(得分:3)

我假设你已经为两个循环迭代提供了足够的公共代码,因此将它作为循环保留是有意义的。您可以轻松地将其写为do ... while循环:

do {
  ....
} while (!(loopTwice = !loopTwice));

答案 1 :(得分:3)

这里只是添加另一种方法,递归!

void MyRecursiveMethod(bool repeat)
{
   // Do something here.

   // Should we do this more than once?
   if(repeat)
     MyRecursiveMethod(false); // Don't do this indefinitely!
}

编辑:如果需要,这也允许您轻松地将其扩展到 n 次迭代,而不仅仅是两次。

例如,将来您决定可能需要执行此操作三次,您可以将其更改为int repeatCount而不是简单的bool,然后再减少每一次。

答案 2 :(得分:2)

使用布尔标志来表示你想循环多少次似乎模糊了你对读者的意图(至少,这个)。我更喜欢这样的东西:

int loops = someFlag ? 2 : 1;
while(loops-- > 0) {

    DoThis(someFlag);
    DoThat(someFlag);
    DoAnotherThing(someFlag);

}

它清楚地表达了你的意图:如果标志为真,则循环2次,如果标志为假则只执行一次。此外,它可以让你很容易在未来修改循环迭代。没有递归,没有附加功能,能够适应所需的迭代次数,可读性等。

修改

添加内部标志以表示在最后一次迭代中始终具有false标志的意图,这仍然适应所需的循环次数。另外,我改为预先递减循环变量,因此内部循环不与0进行比较:

int loops = someFlag ? 2 : 1;
while (--loops >= 0) {
    bool lastIter = loops == 0;

    DoThis(someFlag && !lastIter);
    ...
}

答案 3 :(得分:1)

这种感觉就像一个'倒计时'循环,但有布尔。你可以弄清楚要使用的布尔值:

var iterations = new[] {true,false}.SkipUntil(e => e == loopTwice);
// or
var iterations = new[] {true,false}.Skip(loopTwice ? 0 : 1);
// or
var iterations = loopTwice? new[] {true, false} : new[] {false};

然后使用它们:

foreach (var b in iterations) {
    DoThis(b);
    DoThat(b);
    DoAnotherThing(b);
}

答案 4 :(得分:0)

这样的事情会起作用还是让你感兴趣?

switch (count) {
     case 0:
        break;
     case 1:
        doThisThingSecond();
        goto case: 2;
     case 2:
        doThisThingFirst();
        break;
}

答案 5 :(得分:0)

重新考虑要求之后,我真的建议添加另一种方法。包装另一种方法或一堆方法是一种非常常见的模式(外观等),并且会使您的代码具有可读性。使用Linq和递归的所有这些混淆都会破坏您的原始意图。除非您在20世纪80年代的硬件上运行,否则添加其他方法或变量对代码性能的影响可以忽略不计。

这是我的另一个建议:

void ExecuteWithFlag(bool withFlag)
{
    DoSomething(withFlag);
    DoSomethingElse(withFlag);
    // etc.
}

void Execute()
{
    ExecuteWithFlag(true);
    ExecuteWithFlag(false);
}