使用块后返回的最佳实践

8
哪种方式是更好的做法:在 using 语句内从一个方法中返回一个值,还是先声明一个变量,在内部设置它并在之后返回它?
public int Foo()
{
  using(..)
  {
     return bar;
  }
}

或者

public int Foo()
{
  var b = null;
  using(..)
  {
    b = bar;
  }
  return b;
}
7个回答

9

我更喜欢第一个例子。变量更少,代码更简洁,易于理解,易于维护...

public int Foo()
{
  using(..)
  {
     return bar;
  }
}

5

遵循“少即是多”的原则(实际上只是KISS原则的一种变体),前者更好。它有更少的代码行需要维护,没有语义上的变化和可读性不会减少(可以说这种风格更易于阅读)。


5

来自using语句 - MSDN

使用using语句可确保即使在调用对象方法时发生异常,Dispose也会被调用。您可以通过将对象放置在try块中,然后在finally块中调用Dispose来实现相同的结果;事实上,这就是编译器如何翻译using语句的方式。

来自try-finally (C#参考)

finally用于确保代码块执行无论前面的try块如何退出。

回答您的问题,从using语句返回是可以的。


他询问的是上面哪种做法更好,而不是使用语句的语义学问题。可以说语义学在这里是相关的,但它并没有回答所提出的问题。 - jason
@Jason:说得好。问题的标题是“在using语句中从方法返回是否可以?”你可以看到我不是唯一一个这样阅读问题的人。 - Stan R.
1
@Stan R:我看到可能会有混淆的潜在问题,但是这篇文章明显是在询问最佳实践,而不是finally块是否会执行(即语义)。 - jason

3
第二个显然更好,你可以通过编写测试程序来验证它是否正常工作。 using语句本身不能有值,这是一个限制。假设你有一个名为Open的方法,它返回一个打开的FileStream,并且你想获取文件的长度:
Console.WriteLine(Open().Length);

那里出现了一个错误,你没有处理好FileStream。所以你需要像示例一样写:

long length;

using (FileStream file = Open())
    length = file.Length;

Console.WriteLine(length);

但是通过一个简单的扩展方法,你可以这样编写代码:
Console.WriteLine(Open().Use(file => file.Length));

很好,整洁,FileStream被妥善处理。


整齐,但同时也无法阅读 :-) - Scott P
这很不错。谢谢你提供这个聪明的想法。 - Stan R.
@Scott P - 这本质上与 ? : 操作符相同(等效于 if 的“表达式”)。有些人认为 ? : 比等效的 if 语句不太易读,但我发现有时它可以更清晰。消除变量名通常有助于提高清晰度。 - Daniel Earwicker

2

没有理由不这样做,因为这个using语句会被翻译成一个try...finally块,并且finally部分保证会被执行(即使有返回或未处理的异常)。


1
总有人要指出这一点 - finally块并不是“保证”总会被执行的。它将在明确定义的情况下执行,而在其他情况下则不会执行。 - Daniel Earwicker
1
有一些例子它不会奏效吗? - Jordan Parmer
1
@Earwicker:如果不执行的情况低于0.01%,那么我认为在大多数情况下,我们可以说它是“保证的”。 - John Saunders
1
它保证以与任何其他代码相同的方式运行。 - Joel Coehoorn
@John Saunders - 我认为我们都可以从确保程序崩溃时不继续尝试“清理”(例如删除一堆临时文件,可能会删除错误的文件或破坏我们需要识别问题的证据,或抛出更多异常(遮盖原始异常)中受益。 - Daniel Earwicker
显示剩余6条评论

1

我觉得第二个更好。

public int Foo()
{
  using(..)
  {
     return bar;
  }
}

在使用这种方法时,脑海中会出现一个问题,即我们在 using 中间返回,那么我们包装在 using 中的对象会被处理吗?答案是肯定的, 因为 using 语句只是 try/finally 块的组合,从 try 块返回也是可以的。返回表达式将被评估,然后执行 finally 块,然后方法将返回。所以继续前进吧 :)

1

这真的取决于个人偏好。在这个特定的问题上,你会发现双方都有论据。我个人更喜欢选项1:尽快返回。我认为它更好地表达了代码的意图;没有理由比必须要多停留更长时间。如果你完成了所有的工作,就返回吧。

有时候,你可能会有多个可能的返回点,以及“方法结束”工作(日志记录,清理)可能会导致一个单一的返回语句。这并不可怕,但你通常可以通过finally块或面向切面编程中的方面来处理这些情况。


1
我同意个人偏好的观点。我更喜欢在方法的底部/结尾处进行返回。编码指南通常也规定了这一点。这可能也源于方法有时过长,导致方法难以阅读。将它们保持真正简短,你的方法就能再次变得可读。所以我想这是那种“取决于情况”的答案!从最佳实践的角度来看,据我所知,真的没有一个最好的方法,这更多是个人偏好的问题。 - Dennis van der Stelt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接