![]() |
1
347
这不仅仅是审美 ,但它也降低了成本 maximum nesting level many static analysis tools 提供这方面的度量,作为代码质量的指标之一)。 另一方面,它也使您的方法具有多个退出点,而另一组人认为这是不允许的。 就个人而言,我同意ReSharper和第一组(在一种有例外的语言中,我发现讨论“多个退出点”是愚蠢的;几乎任何东西都可能抛出,因此所有方法中都有许多潜在的退出点)。 关于性能 应该 在每种语言中都是等效的(如果不是在IL级别,那么肯定是在抖动通过代码之后)。理论上这取决于编译器,但实际上今天任何广泛使用的编译器都能够处理比这更高级的代码优化情况。 |
![]() |
2
320
方法中间的回报并不一定是坏事。如果能让代码的意图更清楚,那么最好立即返回。例如:
我从数据库中选择了这个代码 refactoring catalog |
![]() |
3
104
这是一个有点宗教色彩的论点,但我同意ReSharper的观点,你应该选择更少的筑巢。我相信这比从一个函数获得多个返回路径的负面影响更大。 代码可读性和可维护性 . 请记住,许多其他开发人员将来需要阅读您的代码,缩进较少的代码通常更易于阅读。 前提条件 是一个很好的例子,说明在函数开始时可以提前返回。为什么函数其余部分的可读性会受到前提条件检查的影响?
在一个函数中有多个返回不会影响维护程序员的工作。 代码可读性差将导致错误。 |
![]() |
4
70
将其与 看似 等效反演:
所以在某些情况下,什么看起来是正确颠倒的
|
![]() |
5
54
只在函数结束时返回的想法是从语言支持异常的前几天开始的。它使程序能够依赖于能够将清理代码放在方法的末尾,然后确保它将被调用,并且其他程序员不会在方法中隐藏导致跳过清理代码的返回。跳过的清理代码可能导致内存或资源泄漏。 但是,在支持异常的语言中,它不提供此类保证。在支持异常的语言中,任何语句或表达式的执行都可能导致导致方法结束的控制流。这意味着必须通过使用finally或关键字来完成清理。 无论如何,我想说的是,我认为很多人引用了“方法末尾的唯一返回”准则,却不理解为什么这样做是一件好事,减少嵌套以提高可读性可能是一个更好的目标。 |
![]() |
6
34
我想补充一点,倒排的if-s-Guard子句是有名字的。只要我能,我就用它。 我讨厌在一开始有if的地方阅读代码,两屏代码,没有其他。只要反转if并返回。这样就没有人会浪费时间滚动了。 |
![]() |
7
22
它不仅影响美观,还防止代码嵌套。
|
![]() |
8
18
这当然是主观的,但我认为它在两点上有很大的改进:
|
![]() |
9
15
在C语言中,多个返回点是一个问题(在较小程度上是C++),因为它们迫使您在每个返回点之前复制清理代码。通过垃圾收集
归根结底,这取决于你和你的同事觉得什么更容易阅读。 |
![]() |
10
12
保护子句或前置条件(如您可能看到的)检查是否满足某个条件,然后中断程序流。它们非常适合那些你只对一个测试结果感兴趣的地方
您可以反转条件,如果反转条件已满足,则中断
我一刻也不会建议precons会改变你的生活或者让你上床,但是你可能会发现你的代码只是稍微容易一点。 |
![]() |
11
12
就性能而言,这两种方法之间没有明显的区别。
对于哪种方法更可取,存在着相互竞争的思想流派。
另一种观点是,从功能性更强的风格来看,一个方法应该只有一个出口点。函数式语言中的一切都是表达式。所以if语句必须总是有else子句。否则,if表达式并不总是有值。因此,在功能性风格中,第一种方法更自然。 |
![]() |
12
9
可能无法阅读 同样,如果方法非常冗长。也就是说,如果要使用多个返回点,请确保方法简短,否则多个返回点的可读性优势可能会丢失。 |
![]() |
13
9
问题中的情况很清楚,ReSharper是正确的。而不是筑巢
|
![]() |
14
7
就我个人而言,我只喜欢一个出口点。如果您保持方法简短、切中要害,那么很容易实现,并且它为下一个处理代码的人提供了一个可预测的模式。 如。
|
![]() |
15
6
有很多很好的理由 代码是什么样子的 . 但是呢 ? 让我们来看看一些C代码和它的IL编译形式:
这个简单的代码片段可以编译。您可以打开生成的
因此,代码似乎会跳到最后。如果我们使用嵌套代码执行正常的if呢?
结果在IL指令中非常相似。不同之处在于,之前每个条件有两次跳跃:如果
无论如何,程序计数器将始终跳转。 |
![]() |
16
5
从理论上讲,倒转
更多关于分支预测的信息 here |
![]() |
17
4
这完全是有争议的。在提前返回的问题上没有“程序员之间的协议”。据我所知,这总是主观的。
我认为你不会得到这个问题的最终答案。 |
![]() |
18
4
避免多个出口点 可以
但是在99%的情况下,保存额外的构造函数和析构函数调用并不值得失去可读性
|
![]() |
19
3
这里已经有很多有见地的答案,但我还是想指出一个稍微不同的情况:与其先决条件,不如先把它放在函数的顶部。实际上,可以考虑一步一步的初始化,在初始化过程中,您必须检查每一步是否成功,然后继续下一步。在这种情况下,您无法检查顶部的所有内容。 在使用Steinberg的ASIOSDK编写ASIO主机应用程序时,我发现我的代码真的不可读,因为我遵循了嵌套范式。就像上面安德鲁·布洛克提到的那样,它有八层深,我看不到设计上的缺陷。当然,我可以将一些内部代码打包到另一个函数中,然后将剩余的级别嵌套在其中以使其更具可读性,但对我来说这似乎是随机的。 通过用guard子句替换嵌套,我甚至发现了我的一个错误观念,那就是清理代码的一部分应该在函数中更早地出现,而不是在最后出现。对于嵌套的分支,我永远不会看到,你甚至可以说它们导致了我的误解。 因此,这可能是另一种情况,在这种情况下,反转的ifs有助于生成更清晰的代码。 |
![]() |
20
2
这是意见的问题。 我通常的方法是避免单行IFS,并在方法的中间返回。
|
![]() |
21
2
在我看来,如果您只是返回void(或者一些您永远不会检查的无用返回代码),那么提前返回是可以的,并且它可能会提高可读性,因为您避免嵌套,同时明确表示您的函数已经完成。 如果您实际返回的是returnValue,嵌套通常是一种更好的方法,因为您只在一个位置返回returnValue(在末尾-duh),并且它可能会使您的代码在很多情况下更易于维护。 |
![]() |
22
1
我不确定,但我认为R#会尽量避免跳远。当您使用IF-ELSE时,编译器会执行如下操作:
真实条件标签: 说明1 说明 错误的条件标签: ... 说明 端块 若条件为true,则不会跳转,也不会卷展一级缓存,但跳转到false_条件_标签可能非常远,处理器必须卷展自己的缓存。同步缓存很昂贵。R#尝试将远跳转替换为短跳转,在这种情况下,所有指令都已在缓存中的可能性更大。 |
![]() |
23
0
我想这取决于你喜欢什么,如前所述,目前还没有达成一致意见。 |
![]() |
24
0
我的想法是,“在函数中间”的返回不应该如此“主观”。 原因很简单,以下面的代码为例: function do_something( data ){ if (!is_valid_data( data )) return false; do_something_that_take_an_hour( data ); istance = new object_with_very_painful_constructor( data ); if ( istance is not valid ) { error_message( ); return ; } connect_to_database ( ); get_some_other_data( ); return; } 也许第一次“返回”不是那么直观,但这真的节省了。 关于干净代码的“想法”太多了,需要更多的练习才能丢掉“主观”的坏想法。 |
![]() |
25
0
这种编码有几个优点,但对我来说最大的好处是,如果你能快速返回,你可以提高应用程序的速度。IE我知道,因为前提条件X,我可以很快返回错误。这将首先消除错误情况,并降低代码的复杂性。在很多情况下,由于cpu管道现在可以更干净,它可以阻止管道崩溃或交换机。其次,如果您处于循环中,快速中断或返回可以节省大量cpu。一些程序员使用循环不变量来实现这种快速退出,但这样会破坏cpu管道,甚至产生内存寻道问题,这意味着cpu需要从外部缓存加载。但基本上我认为你应该做你想做的,那就是结束循环或函数,而不是仅仅为了实现正确代码的抽象概念而创建复杂的代码路径。如果你唯一的工具是锤子,那么一切看起来都像钉子。 |
![]() |
Luke Hammer · resharper表达式正文格式 7 年前 |
![]() |
SourceSurfer · 我如何添加自己的重拾器模板/狙击手? 7 年前 |
![]() |
doorman · 新建对象时生成道具的代码 7 年前 |