考虑以下代码:
public void doSomething(int input)
{
while(true)
{
TransformInSomeWay(input);
if(ProcessingComplete(input))
break;
DoSomethingElseTo(input);
}
}
假设此过程涉及有限但与输入有关的步骤数;循环的目的是由于算法而自行终止,而不是设计为无限期地运行(直到被外部事件取消为止)。因为检查循环是否应该结束的测试是在逻辑步骤的中间,所以while循环本身目前不检查任何有意义的事情;而是在概念算法的“适当”位置执行检查。
有人告诉我这是错误的代码,因为由于循环结构未检查结束条件,所以它更容易出错。弄清楚如何退出循环会更加困难,并且由于将来的更改可能会意外地忽略或破坏中断条件,因此可能会引发错误。
现在,代码的结构如下:
public void doSomething(int input)
{
TransformInSomeWay(input);
while(!ProcessingComplete(input))
{
DoSomethingElseTo(input);
TransformInSomeWay(input);
}
}
但是,这会重复调用代码中的方法,这违反了DRY。如果TransformInSomeWay
后来被其他方法替换,则必须找到并更改这两个调用(在更复杂的代码中可能不那么明显地存在两个调用)。
您也可以这样写:
public void doSomething(int input)
{
var complete = false;
while(!complete)
{
TransformInSomeWay(input);
complete = ProcessingComplete(input);
if(!complete)
{
DoSomethingElseTo(input);
}
}
}
...但是您现在有了一个变量,其唯一目的是将条件检查移至循环结构,并且还必须多次检查以提供与原始逻辑相同的行为。
就我而言,我说的是,鉴于该代码在现实世界中实现的算法,原始代码最易读。如果您自己经历它,这就是您要考虑的方式,那么对熟悉算法的人来说将是直观的。
那么,哪个更好?通过围绕循环构造逻辑来将条件检查的责任赋予while循环是否更好?还是以需求或算法的概念描述所指示的“自然”方式构造逻辑更好,即使这可能意味着绕过循环的内置功能?
do ... until
构造对于此类循环也很有用,因为它们不必“启动”。