C#:嵌套条件语句与 continue 语句
最近使用 ReSharper 时,建议我通过反转 if
条件并使用 continue
语句来减少某些地方的嵌套。
嵌套条件:
foreach(....)
{
if(SomeCondition)
{
//do some things
if(SomeOtherNestedCondition)
{
//do some further things
}
}
}
继续语句:
foreach(....)
{
if(!SomeCondition) continue;
//do some things
if(!SomeOtherNestedCondition) continue;
//do some further things
}
我理解为什么您希望减少性能和内存问题的嵌套的一些逻辑,以及这两个片段如何相互等同其他,但是从我的开发背景来看,之前示例在阅读代码时更容易理解。
您更喜欢哪种方法?为什么?您是否在日常代码中使用 continue
来代替嵌套的 if 语句?
In using ReSharper recently, it is suggesting I reduce nesting in certain places by inverting if
conditions and using the continue
statements.
nested conditionals:
foreach(....)
{
if(SomeCondition)
{
//do some things
if(SomeOtherNestedCondition)
{
//do some further things
}
}
}
continue statements:
foreach(....)
{
if(!SomeCondition) continue;
//do some things
if(!SomeOtherNestedCondition) continue;
//do some further things
}
I understand some of the logic of why you'd want to reduce nesting for performance and memory issues as well as how the two snippets equate to each other, however from my development background, the before example is easier to follow when reading the code.
Which approach do you prefer and why? Do you use continue
over nested ifs in your everyday code?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
简短的回答:
我倾向于使用缩进,这意味着发生了一些真正的决策逻辑,即。预期有多个可能执行路径的逻辑。
更长的答案:
我通常更喜欢缩进块而不是前面的“中断”语句(
继续
、break
、return
或抛出
)。原因:在我看来,破坏语句通常会使代码更难阅读。如果缩进代码,很容易找到某些决策逻辑发生的位置:这将是缩进较少的代码的第一行。如果您使用带有反转条件的中断语句,则必须做更多的工作来了解代码如何分支以及在什么情况下跳过某些代码。
对我来说有一个值得注意的例外,即在方法开头验证参数。我将此代码格式化如下:
原因:因为我不希望实际抛出这些异常(也就是说,我希望正确调用该方法;调用函数负责检测无效输入) ,IMO),我不想缩进所有其余的代码来处理不应该发生的事情。
Short answer:
I tend to use indentation such that it implies that some real decision logic takes place, ie. logic where more than one possible execution path is expected.
Longer answer:
I usually prefer indented blocks to preceding "breaking" statements (
continue
,break
,return
, orthrow
).Reason: In my opinion, breaking statements generally make code harder to read. If you indent code, it's easy to find the location where some decision logic happens: that'll be the first line further up the code that is indented less. If you use breaking statements with an inverted condition instead, you have to do more work to understand how code branches and under which circumstances certain code is skipped.
There is one notable exception for me, namely validating arguments at the beginning of a method. I format this code as follows:
Reason: Since I don't expect these exceptions to be actually thrown (that is, I expect the method to be invoked correctly; the calling function is responsible to detect invalid input, IMO), I don't want to indent all the rest of the code for something that shouldn't happen.
使用
continue
样式代码;您将如何处理不依赖于 SomeOtherNestedCondition 的第三个操作,这使得代码的顺序很重要,IMO 使其难以维护。例如:
当 SomeOtherNestedCondition 导致
continue;
发生,但 SomeSecondNonNestedCondition 仍应执行时,会发生什么?我会重构每一位“代码”,并使用嵌套的 if() 来调用每个重构的方法,并且保留嵌套结构。
With the
continue
style code; how would you handle a third operation that isn't dependent on SomeOtherNestedCondition, this makes the order of the code important which IMO makes it less maintainable.For example:
What happens when SomeOtherNestedCondition causes the
continue;
to happen, but SomeSecondNonNestedCondition should still execute?I would refactor out each bit of "code" and use nested
if()
s to call each refactored method, and I'd keep the nested structure.结合使用两者。我在循环顶部使用
if(condition) continue;
和if(condition) return;
来验证当前状态,并嵌套if
进一步声明以控制我想要完成的任何事情的流程。Use a combination of the two. I use
if(condition) continue;
andif(condition) return;
at the top of the loop to validate the current state, and nestedif
statements further down to control the flow of whatever I'm trying to accomplish.简单的回答。哪一个更容易阅读和理解。
Simple answer. Which ever one is easier to read and understand.
在内存或性能方面没有区别。底层 IL 只是分支/跳转指令的选择,因此它们是否跳回循环顶部或“else”语句并不重要。
您应该选择更容易阅读的一个。我个人更喜欢避免“继续”,但如果您有很多级别的嵌套,那么您的第二个示例可能更容易理解。
There is no difference in terms of memory or performance. The underlying IL is just a selection of branch/jump instructions so it doesn't really matter whether they jump back to the top of the loop or to the "else" statement.
You should pick whichever is easier to read. I personally prefer to avoid 'continue', but if you have many levels of nesting then your second example can be easier to follow.
使用 continue 使大部分代码处于常规过程代码的级别。
否则,如果有五个检查,您将缩进方法的“内容”10 或 20 个字符,具体取决于缩进大小,而这些是 10/20 个字符,您必须滚动才能看到更长的行。
Using
continue
s makes the bulk of the code on the level of regular procedural code.Otherwise, if there are five checks, you'll indent the "meat" of the method 10 or 20 chars, depending on the indent size, and those are 10/20 chars that you'll have to scroll to see the longer lines.
Continue
原意:当任何条件为 false 时,代码不会被处理。这是情况的示例:输出将是:
Original
continue
meaning: The code won't be processed while any condition is false. Here is an example of the situation:And output will be:
嗯 - 我想,这是你的个人意见。例如,我尝试避免这种嵌套,因为在我看来,这会使代码更难阅读。
如果您比“之后”版本更喜欢“之前”版本,请使用它。
只需配置 ReSharper,它就会建议您真正想要的内容。
永远记住:ReSharper 是一个相当“愚蠢”的重构工具——它无法取代开发人员。它只能通过做一些愚蠢的复制和粘贴工作来帮助他。
即使在 ReSharper 建议相反重构的情况下,ReSharper 所做的一些重构也会导致结果。
因此,不要将 ReSharper 的建议视为最佳实践,而应将其视为您可以采取的可能性。
顺便说一句:您应该在这里考虑性能因素 - 如果性能确实存在显着差异,我会感到惊讶。
Well - I think, that's your personal opinion. I - for example - try to avoid such nesting as it makes the code harder to read in my opinion.
If you like the "before" version more than the "after" one, use it.
Just configure ReSharper so it suggests what you really want it to.
Always keep in mind: ReSharper is a quite "dumb" refactoring tool - it cannot replace the developer. It can only help him by doing some otherwise stupid copy&paste work.
Some refactorings done by ReSharper result even in situations in whcih ReSharper suggests the opposite refactoring.
Therefore, don't see ReSharper's suggestions as best practices but as possibilities you could do.
BTW: You should be driven by performance considerations here - I would be surprised if there are really notable differences in performance.
一般来说,我发现最好总是以任何排除的条件开始语句块,因为它会降低复杂性,但更重要的是在进一步执行之前抛出不兼容的情况,这可以提高代码和内存性能。这也确保了您的条件在维护期间的安全性,即不太可能将无效场景传递到不属于它们的代码中。
另外,我认为两者中的第二个个人更具可读性,因为您没有作用域层混淆了可用的内容,很容易在以后的某一层中创建一个变量,而没有意识到它在另一层中不可用,或者必须管理它们以进行适当的修改等。
这不仅仅是继续循环,而是这也指方法应返回的条件; 而不是让方法启动
它应该始终启动,
As a rule I have found it best to always start statement blocks with any conditions that will except out as it reduces complexity, but more importantly throws out non-compatible circumstances before they are stepped any further which can increase code and memory performance. This also ensures safety of your conditions over a duration through maintenance, that it's less likely to have invalid scenarios passed into code they don't belong in.
Plus I think the second of the two is more readable personally because you don't have the scope layers confusing what's available, it's easy to create a variable in one layer later down the road and not realize it's unavailable in another layer, or having to manage them to be modified appropriately etc.
This isn't just continue in loops, but this also refers to conditions of methods should return; instead of having a method start
it should always start
不应该有显着的性能差异,这都是关于可读性的。我个人认为后者更容易阅读。更少的嵌套,更容易阅读。
There should be no significant performance different, this is all about readability. Personally I think the latter is easier to read. Less nesting, easier to read.