在 void 方法中使用 return 是不好的做法吗?
想象一下下面的代码:
void DoThis()
{
if (!isValid) return;
DoThat();
}
void DoThat() {
Console.WriteLine("DoThat()");
}
在 void 方法中使用 return 可以吗? 它有任何性能损失吗? 或者编写这样的代码会更好:
void DoThis()
{
if (isValid)
{
DoThat();
}
}
Imagine the following code:
void DoThis()
{
if (!isValid) return;
DoThat();
}
void DoThat() {
Console.WriteLine("DoThat()");
}
Is it OK to use a return inside a void method? Does it have any performance penalty? Or it would be better to write a code like this:
void DoThis()
{
if (isValid)
{
DoThat();
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
在这种情况下,您的第二个示例是更好的代码,但这与从 void 函数返回无关,这只是因为第二个代码更直接。 但从 void 函数返回是完全没问题的。
In this case, your second example is better code, but that has nothing to do with returning from a void function, it's simply because the second code is more direct. But returning from a void function is entirely fine.
在这一点上,我不同意你们所有年轻自吹自擂者的观点。
在方法中间使用 return 是一种非常糟糕的做法,无论是 void 还是其他方法,原因已故的 Edsger W. Dijkstra 在近四十年前就已经清楚地阐述过,从著名的“GOTO 语句被认为是有害的”开始”,并继续阅读 Dahl、Dijkstra 和 Hoare 所著的“结构化编程”。
基本规则是每个控制结构和每个模块都应该有一个入口和一个出口。 模块中间的显式返回打破了该规则,并使推理程序的状态变得更加困难,这反过来又使判断程序是否正确变得更加困难(这是一个更强的属性)而不是“它是否有效”)。
“GOTO 语句被认为有害”和“结构化编程”拉开了 20 世纪 70 年代“结构化编程”革命的序幕。 这两部分是我们今天拥有 if-then-else、while-do 和其他显式控制结构的原因,也是高级语言中的 GOTO 语句出现在濒危物种列表中的原因。 (我个人的观点是,它们需要列入灭绝物种名单。)
值得注意的是,消息流调制器是第一个在第一次尝试中就通过验收测试的军事软件,没有偏差、豁免或“是的,但是”这样的废话,是用一种甚至没有 GOTO 语句的语言编写的。
还值得一提的是,Nicklaus Wirth 在 Oberon-07(Oberon 编程语言的最新版本)中更改了 RETURN 语句的语义,使其成为类型化过程(即函数)声明的尾随部分,而不是函数体中的可执行语句。 他对这一变化的解释说,他这样做正是因为以前的形式违反了结构化编程的单出口原则。
I'm going to disagree with all you young whippersnappers on this one.
Using return in the middle of a method, void or otherwise, is very bad practice, for reasons that were articulated quite clearly, nearly forty years ago, by the late Edsger W. Dijkstra, starting in the well-known "GOTO Statement Considered Harmful", and continuing in "Structured Programming", by Dahl, Dijkstra, and Hoare.
The basic rule is that every control structure, and every module, should have exactly one entry and one exit. An explicit return in the middle of the module breaks that rule, and makes it much harder to reason about the state of the program, which in turn makes it much harder to say whether the program is correct or not (which is a much stronger property than "whether it appears to work or not").
"GOTO Statement Considered Harmful" and "Structured Programming" kicked off the "Structured Programming" revolution of the 1970s. Those two pieces are the reasons we have if-then-else, while-do, and other explicit control constructs today, and why GOTO statements in high-level languages are on the Endangered Species list. (My personal opinion is that they need to be on the Extinct Species list.)
It is worth noting that the Message Flow Modulator, the first piece of military software that EVER passed acceptance testing on the first try, with no deviations, waivers, or "yeah, but" verbiage, was written in a language that did not even have a GOTO statement.
It is also worth mentioning that Nicklaus Wirth changed the semantics of the RETURN statement in Oberon-07, the latest version of the Oberon programming language, making it a trailing piece of the declaration of a typed procedure (i.e., function), rather than an executable statement in the body of the function. His explication of the change said that he did it precisely because the previous form WAS a violation of the one-exit principle of Structured Programming.
void 方法中的返回还不错,是 反转
if 的常见做法
语句来减少嵌套。减少方法上的嵌套可以提高代码的可读性和可维护性。
实际上,如果您有一个没有任何 return 语句的 void 方法,编译器将始终生成 ret 指令 在其末尾。
A return in a void method is not bad, is a common practice to invert
if
statements to reduce nesting.And having less nesting on your methods improves code readability and maintainability.
Actually if you have a void method without any return statement, the compiler will always generate a ret instruction at the end of it.
使用防护(与嵌套代码相反)的另一个重要原因是:如果另一个程序员将代码添加到您的函数中,那么他们将在更安全的环境中工作。
考虑:
与:
现在,想象另一个程序员添加了这一行: obj.DoSomethingElse();
显然这是一个简单的情况,但程序员在第一个(嵌套代码)实例中的程序中添加了崩溃。 在第二个示例(带有防护的提前退出)中,一旦通过防护,您的代码就不会意外使用空引用。
当然,一个伟大的程序员不会(经常)犯这样的错误。 但预防胜于治疗——我们可以以完全消除这种潜在错误源的方式编写代码。 嵌套会增加复杂性,因此最佳实践建议重构代码以减少嵌套。
There is another great reason for using guards (as opposed to nested code): If another programmer adds code to your function, they are working in a safer environment.
Consider:
versus:
Now, imagine another programmer adds the line: obj.DoSomethingElse();
Obviously this is a simplistic case, but the programmer has added a crash to the program in the first (nested code) instance. In the second example (early-exit with guards), once you get past the guard, your code is safe from unintentional use of a null reference.
Sure, a great programmer doesn't make mistakes like this (often). But prevention is better than cure - we can write the code in a way that eliminates this potential source of errors entirely. Nesting adds complexity, so best practices recommend refactoring code to reduce nesting.
不好的做法??? 决不。 事实上,如果验证失败,最好通过尽早从方法返回来处理验证。 否则会导致大量嵌套的 if 和 if 语句。 其他的。 提前终止可以提高代码的可读性。
另请检查类似问题的答复:我应该使用return/Continue 语句而不是 if-else?
Bad practice??? No way. In fact, it is always better to handle validations by returning from the method at the earliest if validations fail. Else it would result in huge amount of nested ifs & elses. Terminating early improves code readability.
Also check the responses on a similar question: Should I use return/continue statement instead of if-else?
这不是一个坏习惯(出于已经说明的所有原因)。 然而,一个方法中的返回越多,它就越有可能被分割成更小的逻辑方法。
It's not bad practice (for all reasons already stated). However, the more returns you have in a method, the more likely it should be split into smaller logical methods.
第一个示例是使用保护语句。 来自维基百科:
我认为在方法的顶部有一堆守卫是一种完全可以理解的编程方式。 它基本上是说“如果其中任何一个为真,则不要执行此方法”。
所以一般来说它会像这样:
我认为这样更具可读性:
The first example is using a guard statement. From Wikipedia:
I think having a bunch of guards at the top of a method is a perfectly understandable way to program. It is basically saying "do not execute this method if any of these are true".
So in general it would like this:
I think that's a lot more readable then:
没有性能损失,但是第二段代码更具可读性,因此更容易维护。
There is no performance penalty, however the second piece of code is more readable and hence easier to maintain.
这完全没问题,并且不会造成“性能损失”,但永远不要编写没有括号的“if”语句。
总是
更具可读性; 并且您永远不会意外地假设代码的某些部分不在该语句内,而实际上它们并不在该语句内。
It's perfectly okay and no 'performance penalty', but never ever write an 'if' statement without brackets.
Always
It's way more readable; and you'll never accidentally assume that some parts of the code are within that statement when they're not.
使用防护措施时,请确保遵循某些准则,以免混淆读者。
示例
While using guards, make sure you follow certain guidelines to not confuse readers.
Example
当对象为 null 等时,抛出异常而不是返回任何内容。
您的方法期望对象不为 null,但情况并非如此,因此您应该抛出异常并让调用者处理该异常。
但除此之外,提前返回也不是坏事。
Throw exception instead of returning nothing when object is null etc.
Your method expects object to be not null and is not the case so you should throw exception and let caller handle that.
But early return is not bad practice otherwise.