在void方法中使用return是不好的做法吗?

想象下面的代码:

void DoThis() { if (!isValid) return; DoThat(); } void DoThat() { Console.WriteLine("DoThat()"); } 

在void方法中使用返回是可以的吗? 它有任何性能损失? 或者写一个这样的代码会更好:

 void DoThis() { if (isValid) { DoThat(); } } 

在void方法中返回并不差,通常的做法是将if语句反转以减less嵌套 。

并且减less嵌套在你的方法上可以提高代码的可读性和可维护性。

实际上,如果你有一个没有任何return语句的void方法,那么编译器总是会在其结尾处生成一个ret指令 。

还有一个很好的原因是使用守卫(而不是嵌套代码):如果另一个程序员向你的函数添加代码,他们正在一个更安全的环境中工作。

考虑:

 void MyFunc(object obj) { if (obj != null) { obj.DoSomething(); } } 

与:

 void MyFunc(object obj) { if (obj == null) return; obj.DoSomething(); } 

现在,设想另一个程序员添加行:obj.DoSomethingElse();

 void MyFunc(object obj) { if (obj != null) { obj.DoSomething(); } obj.DoSomethingElse(); } void MyFunc(object obj) { if (obj == null) return; obj.DoSomething(); obj.DoSomethingElse(); } 

显然,这是一个简单的例子,但是程序员在第一个(嵌套代码)实例中添加了一个崩溃。 在第二个例子(带有警卫的早期退出)中,一旦你超越了守卫,你的代码是安全的,无意中使用空引用。

当然,一个伟大的程序员不会像这样(经常)犯这样的错误。 但是预防胜于治疗 – 我们可以通过完全消除这种潜在的错误来源来编写代码。 嵌套增加了复杂性,所以最佳实践build议重构代码以减less嵌套。

不好的做法? 没门。 事实上,如果validation失败,最早通过从方法返回来处理validation。 否则会导致大量的嵌套ifs和elses。 尽早终止可以提高代码的可读性。

还要检查类似问题的回答: 我应该使用return / continue语句而不是if-else吗?

这不是不好的做法(因为所有的原因已经陈述)。 但是,方法中的回报越多,就越有可能将其分解为更小的逻辑方法。

第一个例子是使用警戒语句。 维基百科 :

在计算机编程中,守卫是一个布尔expression式,如果程序执行要在有问题的分支中继续执行,则必须求值为真。

我认为在方法的顶部有一堆警卫是一个完全可以理解的编程方式。 基本上是说“如果其中任何一个都是真的,就不要执行这个方法”。

所以一般来说,它会这样:

 void DoThis() { if (guard1) return; if (guard2) return; ... if (guardN) return; DoThat(); } 

我认为这样更可读:

 void DoThis() { if (guard1 && guard2 && guard3) { DoThat(); } } 

没有性能损失,但是第二块代码更易读,因此更容易维护。

这完全没问题,也没有“性能损失”,但从来没有写过没有括号的“if”语句。

总是

 if( foo ){ return; } 

这是更可读的方式; 而且你永远不会意外地假设代码的某些部分在它们不在的时候在这个语句中。

在这种情况下,你的第二个例子是更好的代码,但是与从void函数返回无关,这仅仅是因为第二个代码更直接。 但是从void函数返回是完全正确的。

我会不同意你这个年轻的whippersnappers。

在一种方法中使用回归,无论是否是无效的,都是非常糟糕的做法,因为近四十年前,由已故的埃德斯·D·迪克斯特拉(Edsger W. Dijkstra)所阐明的理由已经很清楚地阐明了,从着名的“GOTO声明被认为是有害的“,并继续由Dahl,Dijkstra和Hoare撰写的”结构化编程“。

基本规则是每个控制结构和每个模块应该只有一个入口和一个出口。 模块中间的一个明确的回报打破了这个规则,并且使得对程序状态的推理变得更加困难,这反过来又使得更难说出程序是否正确(这是一个更强大的属性而不是“看起来是否工作”)。

“GOTO声明被认为是有害的”和“结构化编程”在20世纪70年代的“结构化编程”革命中脱颖而出。 这两个部分是我们现在有if-then-else,while-do和其他显式控制结构的原因,以及为什么高级语言中的GOTO语句在“Endangered Species”列表中。 (我个人认为他们需要在绝种物种名单上。)

值得注意的是,消息stream调制器是EVER第一次通过验收testing的第一件军事软件,没有任何偏差,豁免或“是,但是”的措辞,是用甚至没有一个GOTO语句。

另外值得一提的是,Nicklaus Wirth改变了Oberon-07(Oberon编程语言的最新版本)中RETURN语句的语义,使其成为types化过程(即函数)声明的尾部,而不是函数体中的可执行语句。 他对变更的解释说,他这样做正是因为前面的forms违反了结构化编程的一个退出原则。

抛出exception,而不是在对象为空等时不返回任何东西

你的方法期望对象不是空的,所以你应该抛出exception,并让调用者处理。

但早退不是其次的做法。