.net 首选哪一种:嵌套If';s或退出子/功能?

.net 首选哪一种:嵌套If';s或退出子/功能?,.net,vb.net,.net,Vb.net,最近我一直在处理遗留的vb.net代码,在代码同行审查期间,建议不要使用Exit Sub/函数,而是将所有功能嵌套在IF语句中 当我最初开始开发时,我习惯于本能地这样做(嵌套IF),它不仅看起来更符合逻辑,而且看起来不那么混乱 然而,在某个时候,我与一个将嵌套IF视为“邪恶”的团队合作,因此我被告知退出子类/函数是首选。我很确定他们制作了一些MS最佳实践材料来支持这一点 所以这个问题是给有经验的开发人员的,哪种方式才是真正的首选?如果您给出了答案,请说明您的来源,或者只提及这是您的团队/公司/个

最近我一直在处理遗留的vb.net代码,在代码同行审查期间,建议不要使用Exit Sub/函数,而是将所有功能嵌套在IF语句中

当我最初开始开发时,我习惯于本能地这样做(嵌套IF),它不仅看起来更符合逻辑,而且看起来不那么混乱

然而,在某个时候,我与一个将嵌套IF视为“邪恶”的团队合作,因此我被告知退出子类/函数是首选。我很确定他们制作了一些MS最佳实践材料来支持这一点

所以这个问题是给有经验的开发人员的,哪种方式才是真正的首选?如果您给出了答案,请说明您的来源,或者只提及这是您的团队/公司/个人首选的,并给出原因

提前谢谢

按要求编辑:代码示例

出口接头:

Private Sub DoSomeWork()
 if not conditionMetFromAnotherFunction() then
      exit Sub 
 end if

 'Method work starts here
End Sub
嵌套IFs:

Private Sub DoSomeWork()
 if conditionMetFromAnotherFunction() then
     'Method work starts here
 end if
End Sub
在代码同行评审期间,建议不要使用Exit子/函数,而是将所有功能嵌套在IF语句中

这是一个可怕的建议。就这么简单。别理它。事实上,通常情况正好相反,特别是在需要嵌套缩进的情况下,或者在检查参数的有效性并可能提前退出的情况下:问题中的代码就是一个很好的例子。请务必在这里提前退出

没有“官方”的消息来源(什么是官方的?),但这是优秀程序员的共识,只有极少数人反对。有关这方面的更多讨论,请参阅


但是,我建议使用
Return
而不是
Exit{Sub | Function}

我建议阅读答案,以便对这个主题进行一个很好的总结

总而言之:单入口/单出口是用语言开发的,在这些语言中,一个函数可以有多个入口点,还可以将返回到代码中的不同位置。它被误解为只允许代码中的一个点,您可以从返回

在子程序中只使用一个return/exit语句的“最佳实践”来自具有显式堆管理的语言,其中子程序的资源在子程序结束时被释放,因此需要控制流通过那里。这不适用于基于.NET或JVM的语言


总的来说,当允许您使用多个返回时,代码的可读性通常更高。

如果您不提前退出函数,您的代码将如下所示:

没有人能告诉我,这是一种比从函数中提前返回更好的样式。

与其他任何样式一样,“视情况而定”。如果在错误的上下文中使用,任何一种样式都可能令人反感

例如,
conditionMetFromAnotherFunction()
检查的是什么?如果它正在检查
DoSomeWork()
的某种必要的前置条件,那么我甚至会通过一个异常,而不是只是静静地退出函数<例如,如果代码>ArgumentException检查传递给函数的参数的有效性,它将非常有用。如果系统中确实有问题,悄悄退出似乎是不对的

对于嵌套条件句,这肯定是混乱的。记住经验法则,函数应该“做一件事”。
检查条件是一件事。因此,在这种情况下,
方法的工作从这里开始
应该只不过是对另一个实际执行该工作的方法的调用。它不应该是许多行代码都包装在一个大的条件中。函数名应该准确地反映它们正在做什么。因此,这个方法是
DoWorkIfConditional
(在设计的示例中),另一个方法是
DoWork


功能在工作前检查前提条件是可以的。如果前提条件不满足,我会考虑抛出一个例外。但这取决于应用程序的实际逻辑,在本例中没有真正传达。

正如David在评论中指出的那样,嵌套的if语句会增加代码的复杂性

想象一下以下(简化的)代码:

或以下

Private Sub DoSomeWork()
    if not conditionMetFromAnotherFunction()
        return
    else if not conditionDependantUponPreviousCondition 
        return
    end if


    ' If we're here, everything's all good
    ' Do the work...
End Sub
如果您的条件变得更复杂,返回将使您更容易理解,在某些条件下,您的代码没有做任何事情,并且使代码更具可读性


否则,您必须阅读所有函数并在心里解析嵌套的if,以确保什么也没做。

IMO嵌套的if很快就会被可怕的意大利面代码击溃。一般来说,如果你深入嵌套你的代码,那么你试图在你的方法中做很多工作,很可能会从重构成更小的部分中受益


话虽如此,有时这是无法避免的,因此没有一个答案适用于所有人。

只要你不使用goto's…:你能展示每个版本的例子吗?仅基于描述,我总是投票反对嵌套条件。如果是另一个抽象层次,它应该转到另一个函数。谢谢Konrad,你知道我可以查找任何官方来源来检查,因为现在我不知道哪个是对的,哪个是错的,哪个是主观的-谢谢。@JL这完全是主观的。我基本上听说的原因是单出口为您提供了一个放置断点的好位置,以检查返回的值,或方法完成后对象的状态。就我个人而言,我更喜欢没有10层嵌套的IFs,并接受没有单一出口的事实。@Jonathan I强烈反对。这当然不是主观的,这里有客观的代码复杂性和质量度量。大量嵌套的代码客观上使理解复杂化。另一方面,提前退出允许读者
Private Sub DoSomeWork()
    if not conditionMetFromAnotherFunction()
        return
    else if not conditionDependantUponPreviousCondition 
        return
    end if


    ' If we're here, everything's all good
    ' Do the work...
End Sub