Eri*_*air 26 language-agnostic loops for-loop while-loop
我只是好奇人们对这个话题的看法.假设我有一个对象数组,我想循环遍历它们以查看对象是否包含某些值,如果是,我想停止循环.哪种更好的做法 - 带有中断的for循环或条件循环?
我提供的示例中的伪代码仅用于参数(它也在ActionScript中,因为这是我最近的主要语言).另外,我不是在寻找关于语法的最佳实践想法.
for break循环:
var i:int;
var isBaxterInMilwaukee:Boolean;
for (i = 0; i < arrayLen; i++)
{
if (myArray[i]["name"] == "baxter"
&& myArray[i]["location"] == "milwaukee")
{
isBaxterInMilwaukee = true;
barkTwice();
break;
}
}
Run Code Online (Sandbox Code Playgroud)
条件循环:
var i:int;
var isBaxterInMilwaukee:Boolean;
while (!isBaxterInMilwaukee && i < arrayLen)
{
if (myArray[i]["name"] == "baxter"
&& myArray[i]["location"] == "milwaukee")
{
isBaxterInMilwaukee = true;
barkTwice();
}
i++;
}
Run Code Online (Sandbox Code Playgroud)
lc.*_*lc. 31
简而言之,您应该选择最容易阅读和维护的版本.
在较旧的时代,我知道突然出现一个循环被认为是禁忌(与goto声明相同).循环应该在循环条件下破坏而在其他任何地方都没有.因此,while循环将成为可行的方法.
(这可能是程序集的延续,其中循环基本上是一个代码块,在结尾处有一个go-to-the-begin-if-true跳转语句.块中的多个条件跳转语句使得调试非常困难;因此,他们应该避免并在最后合并为一个.)
我觉得这个想法今天似乎有所改变,尤其是对于foreach循环和托管世界; 现在真的是风格问题.当然,除了一些纯粹主义者之外,许多人都可以接受突然发现的循环.请注意,我仍然会避免在while循环中使用break,因为这会混淆循环条件并使其混乱.
如果你允许我使用foreach循环,我认为下面的代码是一个很多更容易比while循环哥阅读:
bool isBaxterInMilwaukee;
foreach (var item in myArray)
{
if (item.name == "baxter" && item.location == "milwaukee")
{
isBaxterInMilwaukee = true;
barkTwice();
break;
}
}
Run Code Online (Sandbox Code Playgroud)
然而,随着逻辑的复杂性增加,你可能想要在break
声明附近考虑一个突出的评论,以免它被埋没并且很难找到.
可以说,整个事情应该重构为它自己的函数,而这个函数没有break
找到,但实际上return
是结果(可以随意使用for循环版本):
bool isBaxterInMilwaukee(Array myArray)
{
foreach (var item in myArray)
{
if (item.name == "baxter" && item.location == "milwaukee")
{
barkTwice();
return true;
}
}
return false;
}
Run Code Online (Sandbox Code Playgroud)
正如Esko Luontola指出的那样,将调用移到barkTwice()
此函数之外可能是最好的,因为函数名称中的副作用不明显,也不是在每种情况下都找到Baxter.(或者添加一个布尔参数BarkTwiceIfFound
并更改要读取的行if(BarkTwiceIfFound) barkTwice();
以使副作用清晰.)
对于记录,您也可以在for循环中执行标记检查而不会中断,但我觉得这实际上会损害可读性,因为您不期望for循环定义中有额外条件:
var i:int;
var isBaxterInMilwaukee:Boolean;
for (i = 0; !isBaxterInMilwaukee && i < arrayLen; i++)
{
if (myArray[i]["name"] == "baxter"
&& myArray[i]["location"] == "milwaukee")
{
isBaxterInMilwaukee = true;
barkTwice();
}
}
Run Code Online (Sandbox Code Playgroud)
您还可以使用while循环模拟自动递增机制.我不喜欢这个有几个原因 - 你必须初始化i
为比实际起始值小一个,并且根据你的编译器如何使循环条件逻辑短路,你i
退出循环的值可能会有所不同.然而,对于某些人来说,这是可能的,这可以提高可读性:
var i:int = -1;
var isBaxterInMilwaukee:Boolean;
while (!isBaxterInMilwaukee && ++i < arrayLen)
{
if (myArray[i]["name"] == "baxter"
&& myArray[i]["location"] == "milwaukee")
{
isBaxterInMilwaukee = true;
barkTwice();
}
}
Run Code Online (Sandbox Code Playgroud)
我一直不喜欢breaks
在代码中的使用...在这种情况下它似乎并不重要,但在更多涉及的循环中,它可能会让另一个读取它的编码器感到困惑.通常,它通常导致不理解循环如何终止,直到编码器发现嵌套break
在循环中的深处.通过指定检查循环的每次迭代的标志条件,它使这更清楚.
这个问题类似于return
在方法体内深处的语句,它们不容易被发现(而不是设置retVal
变量并在方法结束时返回).用一个小方法,这似乎很好,但它越大,它就会越混乱.
它不是一个操作效率的东西,它是一个可维护性的东西.
向你的同事询问特定情况下的可读性和可理解性......这才是真正重要的.