try/catch + using,正确的语法

Xaq*_*ron 178 c# using-statement try-catch

哪一个:

using (var myObject = new MyClass())
{
   try
   {
      // something here...
   }
   catch(Exception ex)
   {
      // Handle exception
   }
}
Run Code Online (Sandbox Code Playgroud)

要么

try
{
   using (var myObject = new MyClass())
   {
      // something here...
   }
}
catch(Exception ex)
{
   // Handle exception
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*ood 91

我更喜欢第二个.也可以捕获与创建对象有关的错误.

  • 我认为第一个也有价值,考虑一个DB事务`using(DBConnection conn = DBFactory.getConnection())`,如果发生异常,需要回滚它.在我看来,两者都有自己的位置. (16认同)
  • 我不同意这个建议.如果您希望对象创建抛出错误,那么对该异常*的任何处理必须*走出去.如果对处理的位置存在一些疑问,那么预期的异常必须是其他的 - 除非你提倡捕获任何可能或可能不会预期的随机异常,这是一种典型的反模式(在进程或线程的Unhandled Exception Handler). (11认同)
  • @Jeffrey:我描述的方法对我很有帮助,而且我已经这样做了很长时间。没有人说过*期望*对象创建失败。但是,通过将一个可能*可能*失败的操作包装在一个 `try` 块中,这允许您在出现故障时弹出错误消息,该程序现在能够恢复并通知用户。 (2认同)

che*_*525 34

因为使用块只是try/finally(MSDN)的语法简化,所以我个人会考虑以下内容,但我怀疑它与你的第二个选项有很大不同:

MyClass myObject = null;
try {
  myObject = new MyClass();
  //important stuff
} catch (Exception ex) {
  //handle exception
} finally {
  if(myObject is IDisposable) myObject.Dispose();
}
Run Code Online (Sandbox Code Playgroud)

  • 添加一个处理IDisposable对象的`finally`块就是`using`语句.就个人而言,我喜欢这个而不是嵌入式的"使用"块,因为我认为它更清晰地说明了所有事情发生的地方,而且它们都在同一个"级别".我也喜欢这个嵌入式`using`块几个......但这只是我的偏好. (10认同)
  • 如果您实施了很多异常处理,那么您一定非常喜欢打字!那个"使用"关键字已经存在了一段时间,它的含义对我来说非常清楚.使用它有助于通过将杂乱的数量保持在最低限度来使我的代码的其余部分更清晰. (6认同)
  • 为什么你认为添加`finally`块比`using`语句更可取? (3认同)
  • 从技术上讲,这也不会编译.`不能将null分配给隐式类型的局部变量`;)但我知道你的意思,并且个人更喜欢这个嵌套使用块. (3认同)
  • 这是不正确的.该对象必须在`try`语句之外实例化,以便将其置于`finally`语句中; 否则,它将抛出编译器错误:"使用未分配的局部变量'myObject'" (2认同)

Sch*_*999 20

这取决于.如果您使用的是Windows Communication Foundation(WCF),using(...) { try... }则如果proxy in usingstatement处于异常状态,则无法正常工作,即Disposing此代理将导致另一个异常.

就个人而言,我相信最小的处理方法,即只处理您在执行时意识到的异常.换句话说,如果你知道变量in的初始化using可能抛出一个特殊的异常,我用它包装try-catch.类似地,如果在usingbody中可能发生某些事情,这与变量in没有直接关系using,那么我将其与另一个try特定异常包装起来.我很少使用Exception我的catches.

但我确实喜欢IDisposable,using尽管如此我可能有偏见.


Jef*_*dge 19

如果您的catch语句需要访问using语句中声明的变量,那么inside是您唯一的选择.

如果您的catch语句在处理之前需要使用中引用的对象,那么inside是您唯一的选择.

如果您的catch语句采取未知持续时间的操作,例如向用户显示消息,并且您希望在此之前处置您的资源,那么外部是您的最佳选择.

每当我有一个与此类似的scenerio时,try-catch块通常采用与使用中调用堆栈相同的不同方法.对于方法来说,知道如何处理在其中发生的异常是不常见的.

所以我的一般推荐是在外面的外面.

private void saveButton_Click(object sender, EventArgs args)
{
    try
    {
        SaveFile(myFile); // The using statement will appear somewhere in here.
    }
    catch (IOException ex)
    {
        MessageBox.Show(ex.Message);
    }
}
Run Code Online (Sandbox Code Playgroud)


Sma*_*ery 9

Both are valid syntax. It really comes down to what you want to do: if you want to catch errors relating to creating/disposing the object, use the second. If not, use the first.


Jas*_*n C 8

C# 8.0 开始,您可以using在某些条件下简化语句以摆脱嵌套块,然后它仅适用于封闭块。

所以你的两个例子可以简化为:

using var myObject = new MyClass();
try
{
   // something here...
}
catch(Exception ex)
{
   // Handle exception
}
Run Code Online (Sandbox Code Playgroud)

和:

try
{
   using var myObject = new MyClass();
   // something here...
}
catch(Exception ex)
{
   // Handle exception
}
Run Code Online (Sandbox Code Playgroud)

这两点都很清楚;然后,这将两者之间的选择减少到您想要对象的范围是什么、您想要在哪里处理实例化错误以及何时要处理它的问题。

  • 这是新的最佳答案 (3认同)

Mad*_*uja 6

There is one important thing which I'll call out here: The first one will not catch any exception arising out of calling the MyClass constructor.