“ break”和“ continue”是否是不好的编程习惯?


191

我的老板一直提满不在乎地那么糟糕的程序员使用break,并continue在循环中。

我一直在使用它们,因为它们很有意义。让我向您展示灵感:

function verify(object) {
    if (object->value < 0) return false;
    if (object->value > object->max_value) return false;
    if (object->name == "") return false;
    ...
}

这里的要点是,首先该功能检查条件是否正确,然后执行实际功能。IMO同样适用于循环:

while (primary_condition) {
    if (loop_count > 1000) break;
    if (time_exect > 3600) break;
    if (this->data == "undefined") continue;
    if (this->skip == true) continue;
    ...
}

我认为这使阅读和调试更加容易。但我也看不出任何缺点。


2
无需花费太多时间就忘记哪个人在做什么。

57
否。goto都不是。知道何时使用它们是关键。它们是工具箱中的工具。当它们提供清晰简洁的代码时,您可以使用它们。
orj

67
我对这种编码风格的支持不够强烈。嵌套条件的多个级别比这种方法差得多。我通常对代码风格不抱有好感,但这对我来说几乎是个大难题。
埃米尔·H,

9
显然,您的老板没有编写(足够)的代码。如果他这样做了,他会知道所有关键字(是,甚至goto)在某些情况下都是有用的。
sakisk 2011年

57
糟糕的程序员使用Break and Continue并不意味着好的程序员不会这样做。糟糕的程序员也会同时使用if和while。
mouviciel 2013年

Answers:


240

当在块的开始使用时,作为第一次检查,它们就像先决条件一样工作,因此很好。

在块的中间使用时,周围有一些代码,它们的作用就像隐藏的陷阱,因此很不好。


6
@Klaim:可以争论的是,具有多个退出点的任何例程都是糟糕的例程。一个适当分解的例程应该只做一件事和一件事。
比特商

79
@ bit-twiddler:这是非常C语言的心态。以后可以修改一个临时变量,因此从此处向下20行打错一个错字可能会删除精心制作的结果。但是立即返回(或中断,或继续)是非常明确的:我可以停止阅读,现在因为我知道这不可能被修改的进一步下跌。这对我的小脑袋有好处,确实使遍历代码更容易。
Matthieu M.

15
@Matthieu我同意。当您收到满足该块目的的结果时,退出该块。
Evan Plaice

8
@ bit-twiddler-单出口原则与单责任原则是分开的。我不同意检查总是与单独执行WRT分开。实际上,“单一责任”始终使我感到主观。例如,在二次求解器中,计算判别式是否应单独负责?还是整个二次方程式都是一个责任?我认为这取决于您是否将判别式单独使用-否则,将其视为独立的责任可能是多余的。
2011年

10
答案是经验法则,不是硬性规定。它在大多数情况下都有效,如果在您的上下文中有意义的话,请随时进行破坏。
Klaim 2014年

87

您可以阅读Donald Knuth在1974年发表的论文《结构化编程》中的“转到语句”,其中他讨论了go to结构上理想的各种用法。它们包括的等价breakcontinue语句(很多的用途go to在那里已经发展成为较为有限结构)。您的老板是否会骂Knuth为不良程序员?

(例子给我感兴趣。通常情况下,breakcontinue通过谁喜欢任何的代码一个入口和一个出口的人不被喜欢,那何许人也不赞成多个return语句。)


8
在Pascal上,大多数喜欢功能和过程具有单个入口和出口点的人都是在这里长大的。Pascal并不是我学到的第一门语言,但是它对当今的代码结构产生了深远的影响。人们总是评论读取我的Java代码有多么容易。那是因为我避免了多个出口点以及将声明与代码混合在一起。我尽力在方法顶部声明在方法中使用的每个局部变量。这种做法通过迫使我保持​​方法简洁来避免代码混乱。
比特商2011年

5
Pascal还具有嵌套功能。只是说...
Shog9

6
据我所记得,在过去,人们不喜欢函数中的多个return语句的主要原因是因为调试器无法正确处理它们。在函数的末尾设置断点确实很痛苦,但是由于使用了更早的return语句,所以您从未遇到过断点。对于如今的每个编译器,这不再是一个问题。
Dunk

28
@ bit-twiddler:我不太确定。我今天仍在使用Pascal,我通常将“单入口单出口”或至少其单出口部分视为“崇拜”编程。我只考虑BreakContinueExit在我的工具箱中的工具; 我在使代码易于理解的地方使用它们,而在不使代码难以阅读的地方不使用它们。
梅森惠勒

2
@ bit-twiddler:赞成。我还要补充一点,一旦您可以轻松在屏幕上放置块,则多个出口点的麻烦就大大减少了。
Shog9

44

我不认为他们是坏人。它们不好的想法来自结构化编程的时代。与一个功能必须具有单个入口点和单个出口点(即return每个功能仅一个出口点)的概念有关。

如果您的函数很长,并且有多个嵌套循环,那么这是有道理的。但是,您的函数应该短一些,并且应该将循环及其主体包装成它们自己的短函数。通常,将功能强制为一个出口会导致逻辑混乱。

如果函数很短,如果有一个循环,或者最糟糕的是有两个嵌套循环,并且如果循环体很短,则很清楚a break或a的continue作用。同样清楚的是,多个return语句可以做什么。

这些问题在Robert C. Martin的“清洁代码”和Martin Fowler的“重构”中得到了解决。


12
“使功能变小。然后使它们变小”-Robert C. Martin。我发现这行之有效。每次您在函数中看到需要注释说明其功能的代码块时,请将其包装到带有描述性名称的单独函数中。即使只有几行,甚至只使用一次。这种做法消除了大多数与中断/继续或多次收益有关的问题。
迪马

2
@Mikhail:循环复杂度通常与SLOC密切相关,这意味着建议可以简化为“不要编写长函数”。
John R. Strohm

3
单一出口点的想法被广泛误解。从前,函数不必返回其调用者。他们可能会回到其他地方。这通常是用汇编语言完成的。Fortran为此有一个特殊的构造。您可以传入在&开头的语句号CALL P(X, Y, &10),并且在出现错误的情况下,函数可以将控制权传递给该语句,而不是返回到调用点。
凯文·克莱恩

例如,与Lua一起使用的@kevincline。
2014年

1
@cjsimon,你明白了。不仅功能应该很小。班级也应该很小。
迪马

39

糟糕的程序员讲的是绝对的(就像Sith一样)。优秀的程序员尽可能使用最清晰的解决方案(所有其他条件都相同)。

频繁使用Break and Continue使代码难以遵循。但是,如果替换它们使代码更难遵循,那么这将是一个糟糕的更改。

您给出的示例肯定是一种情况,应该用更优雅的方式代替断断续续。


是的,我夸大了条件的数量以提供退出案例的例子。
米哈伊尔(Mikhail)

9
您建议的替换代码示例是什么?我认为这是守卫声明的一个相当合理的例子。
simgineer

在我看来,“可能的最清晰解决方案”总是……可能吗?怎么可能没有“最清晰”的解决方案?但是,我不是绝对主义者,所以也许你是对的。

@nocomprende我不确定你在说什么。这里的“可能”并不表示不存在最佳解决方案-只是完美,最终的清晰度不是问题。毕竟这是主观的。
马修(Matthew)阅读了

22

大多数人认为这是个坏主意,因为这种行为不容易预测。如果您正在阅读代码,并且看到while(x < 1000){}它会一直运行到x> = 1000 ...但是如果中间有中断,那将不成立,因此您不能真正相信自己的代码循环播放...

这是人们不喜欢GOTO的相同原因:当然,它可以很好地使用,但也可能导致令人讨厌的意大利面条代码,该代码在各个部分之间随机跳跃。

就我自己而言,如果我要执行一个在多个条件下中断的循环,while(x){}那么我需要在需要中断时将X切换为false。最终结果将是相同的,并且阅读该代码的任何人都将更仔细地研究改变X值的事物。


2
+1讲得很好,而+1(如果我可以再做一遍)的while(notDone){ }方法。
FrustratedWithFormsDesigner

5
Mikhail:中断的问题是循环的最终条件永远不会简单地放在一个地方。这使得很难预测循环后的后置条件。在这种微不足道的情况下(> = 1000),这并不困难。添加许多if语句和不同级别的嵌套后,确定循环的后置条件将变得非常非常困难。
S.Lott

S.Lott完全用力击中了头部。控制迭代的表达式应包括为了继续迭代必须满足的所有条件。
比特币2011年

6
替换break;x=false;不会使您的代码更清晰。您仍然必须在正文中搜索该语句。而且,在这种情况下,x=false;您必须检查它是否不会x=true;进一步下降。
Sjoerd

14
当人们说“我看到x并且我假设y,但是如果您执行z,则该假设不成立”时,我倾向于认为“因此,不要做出这个愚蠢的假设”。许多人会将其简化为“当我看到while (x < 1000)它会运行1000次时”。好吧,有很多原因导致这个错误,即使x最初为零也是如此。例如,谁说x循环中精确地增加了一次,却从未以其他方式修改过?即使是您自己的假设,也仅仅是因为某些设置x >= 1000并不意味着循环将结束-可能会在检查条件之前将其重新设置在范围内。
Steve314,2011年

14

是的,您可以[重新]编写没有break语句的程序(或从循环中间执行相同操作的返回值)。但是您可能必须引入其他变量和/或代码重复,这通常会使程序更难以理解。因此,Pascal(编程语言)非常糟糕,特别是对于初学者而言。您的老板基本上希望您使用Pascal的控制结构进行编程。如果Linus Torvalds穿着您的鞋子,他可能会向您的老板展示中指!

有一个计算机科学结果叫做Kosaraju的控制结构层次结构,该结果可以追溯到1973年,并在1974年Knuth着名的有关goto的著名论文中提到。(顺便提一下,Knuth的论文已经由David Thornley推荐过了。 。)S. Rao Kosaraju在1973年证明的是,不可能在不引入额外变量的情况下,将深度为n的多级中断的所有程序重写为中断深度小于n的程序。但是,可以说这仅仅是一个理论上的结果。(只需添加一些额外的变量?!当然,您可以这样做来取悦您的老板...)

从软件工程的角度来看,更重要的是埃里克·罗伯茨(Eric S. Roberts)在1995年发表的一篇题​​为“ 循环退出和结构化编程:重新开放辩论”的论文http://cs.stanford.edu/people/eroberts/papers/SIGCSE- 1995 / LoopExits.pdf)。罗伯茨总结了他之前其他人进行的一些实证研究。例如,当一组CS101型学生被要求为实现在数组中顺序搜索的函数编写代码时,研究的作者对使用中断/返回/跳转来退出找到元素时的顺序搜索循环:

我还没有找到一个使用[此样式]尝试过程序的人,但该人提供了错误的解决方案。

罗伯茨还说:

试图解决问题而未使用for循环的显式返回的学生的情况要差得多:在尝试该策略的42名学生中,只有七名设法产生了正确的解决方案。该数字表示成功率不到20%。

是的,您可能比CS101的学生更有经验,但是如果没有使用break语句(或等效地从循环中间返回/转到),最终您将编写代码,尽管结构合理,但在额外逻辑方面足够多变量和代码重复,可能有人会在尝试遵循老板的编码风格时在其中放入逻辑错误。

我还要在这里说罗伯茨的论文对普通程序员来说更容易理解,因此比Knuth的论文读起来更好。它也更短,涵盖了一个狭窄的主题。您甚至可以向老板推荐它,即使他是管理层而不是CS类型。


2
尽管结构化编程是我多年来的方法,但在最近的几年中,他们在第一时间就有机会完全使用显式退出。这样可以加快执行速度,并几乎消除了导致无限循环(挂起)的逻辑错误。
DocSalvager,2015年

9

我不考虑使用这两种不良做法中的任何一种,但是在同一循环中使用过多它们应该重新考虑在循环中使用的逻辑。谨慎使用它们。


:)是的,我所提供的例子是概念
米哈伊尔·

7

您给出的示例不需要中断也可以继续:

while (primary-condition AND
       loop-count <= 1000 AND
       time-exec <= 3600) {
   when (data != "undefined" AND
           NOT skip)
      do-something-useful;
   }

我在您的示例中遇到的4行问题是,它们全都处于同一水平,但是它们执行不同的操作:有些中断,有些继续...您必须阅读每一行。

在我的嵌套方法中,您越深入,代码就越“有用”。

但是,如果深入您发现停止循环的原因(除了主要条件),则可以使用中断或返回。与使用在顶级条件下进行测试的额外标志相比,我更愿意这样做。中断/返回更直接;它比设置另一个变量更好地说明了意图。


+1,但实际上您的<比较需要<=与OP解决方案相匹配
El Ronnoco 2011年

3
在大多数情况下,如果一个人太深以至于需要使用中断/返回来管理流控制,那么一个人的功能/方法就太复杂了。
比特商2011年

6

“坏处”取决于您如何使用它们。我通常仅在循环构造中使用中断,这样才能节省我无法通过算法重构保存的周期。例如,循环遍历一个集合以查找具有特定属性值设置为true的项目。如果您只需要知道其中一个项目将此属性设置为true,那么一旦达到该结果,就可以适当地中断以终止循环。

如果使用中断不会使代码特别易于阅读,缩短运行时间或以显着方式节省处理周期,那么最好不要使用它们。我倾向于尽可能使用“最低公分母”进行编码,以确保跟随我的任何人都可以轻松查看我的代码并弄清楚发生了什么(我并不总是成功的)。休息减少了,因为它们确实引入了奇数的进/出点。被误认为他们的行为很像一个过时的“ goto”声明。


我同意这两点!关于您的第二点-我认为按照我的原始帖子比较容易,因为它的读法像英语。如果您在1条if语句中包含条件组合,那么几乎无法确定if执行true会发生什么。
米哈伊尔(Mikhail)

@Mikhail:您提供的示例对于特定的真实感有点无私。如我所见,这些样本清晰,简洁,更易于阅读。大多数循环不是那样。大多数循环都在执行其他某种逻辑,并且条件复杂得多。在这种情况下,中断/继续可能不是最佳用法,因为它会使读取时的逻辑混乱。
乔尔·埃瑟顿

4

绝对不是...是的,使用goto不好,因为它会使程序的结构恶化,并且也很难理解控制流程。

但是如今使用诸如break和这样的语句continue是绝对必要的,并且根本不被视为不良的编程习惯。

而且也不难理解break和使用控制流continue。在类似switch的构造中,该break声明是绝对必要的。


2
自从1981年第一次学习C以来,我就没有使用过“ continue”。这是一种不必要的语言功能,因为continue语句绕过的代码可以由条件控制语句包装。
比特商2011年

12
在这种情况下,我更喜欢使用continue,因为这样可以确保我的代码不会变成箭头代码。我比goto类型语句更讨厌箭头代码。我也将其读为:“如果此语句为真,则跳过此循环的其余部分,并继续下一次迭代。” 它在for循环的开始时非常有用(在while循环中不太有用)。
jsternberg 2011年

@jsternberg为胜利!:-)
Notinlist 2012年

3

基本概念来自能够对程序进行语义分析。如果您只有一个入口和一个出口,则表示可能状态的数学要比管理分叉路径容易得多。

在某种程度上,这种困难反映出了能够在概念上对您的代码进行推理。

坦白说,您的第二个代码并不明显。到底在做什么 是继续“继续”,还是“下一步”循环?我不知道。至少您的第一个例子很清楚。


当我在一个项目中经理必须使用它们时,我不得不使用流程图来记住它的使用,并且几个退出路径确实使代码更加混乱……
umlcat 2011年

您的“坦率”评论是句法上的-“下一个”是perl的东西;正常语言使用“继续”来表示“跳过此循环”
Mikhail

@Mik,也许“跳过此迭代”会是一个更好的描述。您真正的IM Pedantic博士
Pete Wilson

@Mikhail:好的。但是,当一种语言使用多种语言工作时,如果两种语言之间的语法不通用,则可能导致错误。
保罗·内森

但是数学不是编程。代码比数学更具表现力。我知道单次进入/单次退出可能使流程图看起来更好,但付出了什么代价(即在哪里中断/返回可以使代码性能更好)?
Evan Plaice

3

我将用第二个代码段替换

while (primary_condition && (loop_count <= 1000 && time_exect <= 3600)) {
    if (this->data != "undefined" && this->skip != true) {
        ..
    }
}

并非出于任何简洁的原因-实际上,我认为这更容易阅读,也可以让别人了解正在发生的事情。一般而言,循环的条件应完全包含在循环的条件下,而不是随处可见。但也有一些情况下break,并continue能帮助可读性。breakcontinue我可能添加的还要多:D


虽然我不同意“我实际上认为这更容易阅读”,但确实实现了与上述代码完全相同的目的。到目前为止,我从未真正将'break'视为短路操作者,但这是很有意义的。至于“通常来说,循环的条件应完全包含在那些循环条件之内”,在处理foreach循环时您会做什么,因为实际上没有办法在循环定义中插入条件逻辑?
Evan Plaice

@Evan该条件不适用于foreach循环,因为这只会迭代集合中的每个项目。一for环是,它不应该有一个条件结束点类似。如果确实需要条件终点,则需要使用while循环。
El Ronnoco 2011年

1
@Evan我确实明白了你的意思-即“如果需要打破foreach循环该怎么办?” -好吧,break从循环来看,我认为应该只有一个最大值。
El Ronnoco 2011年

2

我不同意你的老板。有正确的地方break,并continue可以用来。实际上,将观念和异常处理引入现代编程语言的原因是,仅仅使用不能解决所有问题structured techniques

附带说明一下, 我不想在这里进行宗教性的讨论,但是您可以将代码重构为更具可读性,如下所示:

while (primary_condition) {
    if (loop_count > 1000) || (time_exect > 3600) {
        break;
    } else if ( ( this->data != "undefined") && ( !this->skip ) ) {
       ... // where the real work of the loop happens
    }
}

另一方面

我个人不喜欢( flag == true )in条件语句的使用,因为如果变量已经是一个布尔值,那么您将引入一个附加比较,当布尔值具有所需的答案时就需要进行比较-除非您确定您的编译器会优化额外的比较。


我已经为这个问题困扰了多年。您的方式('if(flag){...}')更为简洁,也许看起来更像'professional'或'expert'。但是,您知道,这通常意味着读者/维护者必须短暂打断自己才能回忆起构造的含义。并确保测试的意义。目前,我正在使用'if(flag == true){...}'只是因为它似乎是更好的文档。下个月?皇后莎贝?
皮特·威尔逊

2
@Pete-这个词不是很简洁,但是很优雅。您可以随意安排所有内容,但是如果您担心读者/维护者不明白a boolean是什么,或者简洁/优雅的术语意味着什么,那么也许您最好雇用一些更聪明的维护者;-)
Zeke Hansell

@Pete,我也支持有关生成代码的声明。通过在计算表达式的布尔值之前将标志与常量值进行比较,您可以进行另一次比较。为什么要使难度变得比必需的难,flag变量已经具有所需的值!
Zeke Hansell

+1好工作。绝对比以前的示例优雅得多。
Evan Plaice

2

我同意你的老板。它们之所以不好是因为它们会产生高度复杂的方法。这种方法难以阅读且难以测试。幸运的是,有一个简单的解决方案。将循环体提取到单独的方法中,其中“继续”变为“返回”。“返回”更好,因为“返回”结束之后-不必担心本地状态。

对于“ break”,将循环本身提取到一个单独的方法中,将“ break”替换为“ return”。

如果提取的方法需要大量的参数,则表示要提取类-将它们收集到上下文对象中。


0

我认为这是一个嵌套在多个循环中的唯一问题。很难知道您要进入哪个循环。也可能很难遵循续集,但是我认为真正的痛苦来自于中断-逻辑可能难以遵循。


2
实际上,很容易看出您是否正确缩进,使这些语句的语义内部化并且不太困。

@delnan-这是很多假设;)
davidhaskins 2011年

2
是的,尤其是最后一个。
Michael K

好吧,无论如何,#1都是认真编程所必需的,#2应该被称为程序员的每个人所期望,并且#3通常是非常有用的;)

一些语言(仅我知道的脚本)支持break 2;对于其他人,我猜是使用了临时的布尔标志
Mikhail

0

只要它们不像下面的示例那样用作伪装的goto:

do
{
      if (foo)
      {
             /*** code ***/
             break;
      }

      if (bar)
      {
             /*** code ***/
             break;
      }
} while (0);

我对他们很好。(示例在生产代码中显示)


您会建议在这种情况下创建函数吗?
米哈伊尔(Mikhail)

是的,如果不可能的话,简单地转到。当我看到一个动作时,我认为是重复,而不是上下文来模拟跳跃。
SuperBloup

哦,我同意,我只是问你要怎么做:)计算机科学家反复这样做
Mikhail

0

我不喜欢这两种风格。这是我希望的:

function verify(object)
{
    if not (object->value < 0) 
       and not(object->value > object->max_value)
       and not(object->name == "") 
       {
         do somethign important
       }
    else return false; //probably not necessary since this function doesn't even seem to be defined to return anything...?
}

我真的不喜欢使用return中止功能。感觉就像是滥用return

使用break也不总是很容易阅读。

更好的可能是:

notdone := primarycondition    
while (notDone)
{
    if (loop_count > 1000) or (time_exect > 3600)
    {
       notDone := false; 
    }
    else
    { 
        skipCurrentIteration := (this->data == "undefined") or (this->skip == true) 

        if not skipCurrentIteration
        {
           do something
        } 
        ...
    }
}

嵌套更少,复杂的条件被重构为变量(在实际程序中,您必须具有更好的名称,显然...)

(以上所有代码均为伪代码)


11
与我在上面键入的内容相比,您真的更喜欢3级嵌套吗?
米哈伊尔(Mikhail)

@Mikhail:是的,否则我会将条件的结果分配给变量。我觉得更容易比的逻辑理解breakcontinue。异常结束循环感觉很奇怪,我不喜欢它。
FrustratedWithFormsDesigner

1
具有讽刺意味的是,您误解了我的条件。continue意味着跳过功能转到下一个循环;而不是“继续执行”
Mikhail

@Mikhail:啊。我不经常使用它,当我阅读它时,我对含义感到困惑。我不喜欢的另一个原因。:P给我一点时间更新...
FrustratedWithFormsDesigner

7
太多的嵌套会破坏可读性。有时,避免中断/继续介绍了你的条件测试反相你的逻辑的必然性,这可能会导致一个什么样的代码做什么误解-我想说的是
齐克·汉塞尔

0

否。这是解决问题的一种方法,还有其他解决方法。

当前许多主流语言(Java,.NET(C#+ VB),PHP,编写自己的语言)都使用“ break”和“ continue”跳过循环。他们都“结构化goto”句子。

没有他们:

String myKey = "mars";

int i = 0; bool found = false;
while ((i < MyList.Count) && (not found)) {
  found = (MyList[i].key == myKey);
  i++;   
}
if (found)
  ShowMessage("Key is " + i.toString());
else
  ShowMessage("Not found.");

跟他们:

String myKey = "mars";

for (i = 0; i < MyList.Count; i++) {
  if (MyList[i].key == myKey)
    break;
}
ShowMessage("Key is " + i.toString());

请注意,“ break”和“ continue”代码较短,通常将“ while”语句转换为“ for”或“ foreach”语句。

两种情况都与编码风格有关。我不想使用它们,因为冗长的样式使我可以更好地控制代码。

实际上,我在一些项目中工作,在这些项目中必须使用这些句子。

一些开发人员可能认为它们不是必需的,但是假设,如果我们必须删除它们,则我们也必须删除“ while”和“ do while”(“ repeat直到”,您pascal的人);-)

结论,即使我不想使用它们,我也认为它是一种选择,而不是不好的编程习惯。


对不起,很抱歉,但是您的第二个示例缺少未找到键的输出(因此,它看起来短得多了)。
FrustratedWithFormsDesigner

2
更不用说第一个示例仅在键是列表中的最后一个键时才有效。
米哈伊尔(Mikhail)

完全是@FrustratedWithFormsDesigner。我提出理由来说明为什么该方法更可取;-)
umlcat 2011年

但是,您有两个具有不同语义的例程。因此,它们在逻辑上并不等效。
比特币2011年

2
您的第二个示例有两个错误,一个是语法错误,另一个是逻辑错误。1.它不会编译,因为没有在for循环的范围之外声明迭代器(因此在字符串输出中不可用)。2.即使迭代器是在循环外部声明的,如果在集合中未找到键,则字符串输出也会打印列表中最后一项的键。
Evan Plaice

0

我不反对continue,并break在原则上,但我认为他们是非常,很多时候可以通过一些更好的替代低级别的构造。

我在这里以C#为例,考虑要遍历集合的情况,但是我们只希望满足某些谓词的元素,并且我们最多只希望进行100次迭代。

for (var i = 0; i < collection.Count; i++)
{
    if (!Predicate(item)) continue;
    if (i >= 100) break; // at first I used a > here which is a bug. another good thing about the more declarative style!

    DoStuff(item);
}

这看起来很干净。这不是很难理解。我认为从声明性的角度来看会有所收获。将其与以下内容进行比较:

foreach (var item in collection.Where(Predicate).Take(100))
    DoStuff(item);

也许Where和Take调用甚至都不应该使用此方法。也许应该在将集合传递给此方法之前完成此过滤。无论如何,通过远离低级内容,而将更多的精力放在实际的业务逻辑上,可以更清楚地了解我们真正感兴趣的内容。将我们的代码分成更能遵循良好设计规范的内聚模块变得更加容易,因此上。

低级内容仍将存在于代码的某些部分中,但是我们希望尽可能地隐藏它,因为它需要花大量的精力来代替我们思考业务问题。


-1

Code Complete有一个很好的部分,关于使用goto和例程或循环的多次返回。

一般来说,这不是一个坏习惯。breakcontinue确切说出接下来会发生什么。我同意这一点。

Steve McConnell(Code Complete的作者)使用了与您几乎相同的示例,以展示使用各种goto语句的优势。

但是,过度使用breakcontinue可能导致复杂且不可维护的软件。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.