try / catch + using,正确的语法

时间:2011-01-04 03:53:54

标签: c# try-catch using-statement

哪一个:

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

OR

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

9 个答案:

答案 0 :(得分:88)

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

答案 1 :(得分: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();
}

答案 2 :(得分:19)

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

就个人而言,我相信最小的处理方法,即只处理你在执行时知道的异常。换句话说,如果你知道using中变量的初始化可能抛出一个特定的异常,我用try-catch包装它。类似地,如果在using体内可能发生某种情况,这与using中的变量没有直接关系,那么我将其与另一个try包装在一起,用于该特定异常。我很少在Exception es。

中使用catch

但我确实喜欢IDisposableusing,所以我可能有偏见。

答案 3 :(得分:18)

如果你的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);
    }
}

答案 4 :(得分:9)

两者都是有效的语法。这真的取决于你想要做什么:如果你想捕获与创建/处理对象有关的错误,请使用第二个。如果没有,请使用第一个。

答案 5 :(得分:6)

我在这里有一件重要的事情:第一个将捕获因调用MyClass构造函数而产生的任何异常。

答案 6 :(得分:2)

C# 8.0 on中,您可以在某些情况下简化using语句以摆脱嵌套块,然后将其仅应用于封闭块。

因此,您的两个示例可以简化为:

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

并且:

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

两者都很清楚;然后将这两者之间的选择减少到您想要对象范围的大小,要处理实例化错误的位置以及何时处置它的问题。

答案 7 :(得分:1)

如果您在Using()块中初始化的对象可能会抛出任何异常,那么您应该使用第二种语法,否则两者同样有效。

在我的场景中,我必须打开一个文件,然后在我正在Using()块中初始化的对象的构造函数中传递filePath,如果filePath错误/为空,它可能会抛出异常。所以在这种情况下,第二种语法是有意义的。

我的示例代码: -

try
{
    using (var obj= new MyClass("fileName.extension"))
    {

    }
}
catch(Exception ex)
{
     //Take actions according to the exception.
}

答案 8 :(得分:1)

从C#8.0开始,我更喜欢像这样使用第二个

public class Person : IDisposable
{
    public Person()
    {
        int a = 0;
        int b = Id / a;
    }
    public int Id { get; set; }

    public void Dispose()
    {
    }
}

然后

static void Main(string[] args)
    {

        try
        {
            using var person = new Person();
        }
        catch (Exception ex) when
        (ex.TargetSite.DeclaringType.Name == nameof(Person) &&
        ex.TargetSite.MemberType == System.Reflection.MemberTypes.Constructor)
        {
            Debug.Write("Error Constructor Person");
        }
        catch (Exception ex) when
       (ex.TargetSite.DeclaringType.Name == nameof(Person) &&
       ex.TargetSite.MemberType != System.Reflection.MemberTypes.Constructor)
        {
            Debug.Write("Error Person");
        }
        catch (Exception ex)
        {
            Debug.Write(ex.Message);
        }
        finally
        {
            Debug.Write("finally");
        }
    }