拥有终止子句时的最佳做法是什么...请参阅说明:)
情况如下:
我们有一个名为FullScreenEnabled的布尔属性。我们输入一些方法,并且当FullScreenEnabled为true时,将执行此方法中的代码。我们在日常编程中使用以下两种方法中的哪一种:
private bool FullScreenEnabled { get; set; } // Check if FullScreenEnabled is false and return; private void Case1() { if (FullScreenEnabled == false) { return; } // code to be executed goes here! } // Surround the code by an if statement. private void Case2() { if (FullScreenEnabled) { // code to be executed goes here! } }
解决方案
两种方法均未发布。我们应该阅读编辑帮助,以确保代码实际出现。
private void MyMethod(bool arg){ if(arg) return; //do stuff };
(投票)
private void MyMethod(bool arg){ if(!arg){ //do stuff } }
(投票)
我通常更喜欢第一个版本(在方法开始时进行保全)。它导致更少的嵌套,从而稍微增加了可读性。如果我们决定以后不再需要检查条件,则在第一个版本中删除if条件也将更加容易,尤其是当我们进行多次检查时。另外,它可以很容易地用一行编写:if(!FullScreenEnabled)return;
这取决于方法的长度和复杂性。如果该方法很短,则在if中嵌套是没有问题的(并且可能会更清楚)。如果该方法具有许多嵌套语句,则立即返回将减少必要的缩进量,并可能会稍微提高可读性。
这是关于应该测试是肯定的还是否定的,即,如果不满足条件,则从方法开始处返回,或者仅当满足条件时才执行代码。在短方法中,我会选择后一种情况;在长方法中,我会选择前一种情况。当要测试多个条件时,我总是会选择提前退出。但这并没有真正的改变。
但是请注意,在示例中是与false的比较。我们应该改写!FullScreenEnabled。使代码更具可读性。
if (!FullScreenEnabled) throw new InvalidOperationException("Must be in fullscreen mode to do foo.");
我的两分钱,这是值得的。
两种方法都相同。
但是,如果我们为单元测试运行代码覆盖率指标,则if(!FullScreenEnabled)return;将被计为一个单独的块,我们必须创建一个单元测试来覆盖它以达到100%。
当然,即使使用其他方法,我们也可能希望进行单元测试,以验证FullScreenEnabled为false时是否未执行代码。但是,如果我们作弊并且不写,我们仍然会得到100%的收益。 :-)
如果添加案例,则第一种方法(使用保护子句)可以更好地扩展。第二种方法的问题是,添加更多的if语句将导致代码呈现出箭头反模式,其中代码开始像箭头一样被识别。
下面有一篇非常好的文章对此进行了更详细的说明:
编码恐怖:扁平化箭头代码
我会采用第一种方法,我发现它比第二种方法更具可读性。
基本上我认为:
- if(FullScreenEnabled == false)比if(FullScreenEnabled)更具可读性。
- 如果我们始终将"健全性"检查放在方法的开头,则该方法将获得一个很好的结构,该结构非常易于理解。
但是我认为这里有一条细线是不需要越过的,将" return"语句放在方法中间的太多地方确实会使它变得更复杂