捕获使用块内的异常与使用块外的异常 - 哪个更好?

时间:2009-05-26 16:40:50

标签: c# c#-3.0

这两段代码之间是否有任何区别?哪种方法更好。

try
{
    using()
    { 
      //Do stuff
    }
}
catch
{
    //Handle exception
}


using()
{
    try
    {
         //Do stuff
    }
    catch
    {
        //Handle exception
    }
}

7 个答案:

答案 0 :(得分:30)

存在差异,但它归结为使用块创建自己的try和scope块。

try
{
    using(IDisposable A = GetDisposable())
    { 
      //Do stuff
    }
}
catch
{
    //Handle exception
    // You do NOT have access to A
}


using(IDisposable A = GetDisposable())  //exception here is uncaught
{
    try
    {
         //Do stuff
    }
    catch
    {
        //Handle exception
        // You DO have access to A
    }
}

答案 1 :(得分:8)

这些块之间存在差异。在第二种情况下,如果在using()行中抛出异常,则不会捕获异常(例如,实例化IDisposable对象并且构造函数抛出异常)。哪一个更好将取决于您的具体需求。

答案 2 :(得分:5)

是。在第一个中,您正在“使用”的资源将在执行catch块之前被释放。在后来,它将在之后处理。而且,“foo”语句不在catch子句的范围内。 “使用”块是几乎语法糖,这样

using (foo)
{
}

try
{
  foo;
}
finally
{
  foo.Dispose();
}

没有上下文,哪种行为“更好”并不明显。

答案 3 :(得分:3)

最终,您可以结合使用这两种方法来克服缺点

IFoo f;
try{
  f = new Foo();
  f.Bar();
catch{
  // Do something exceptional with f
} finally{
  if(f != null) f.Dispose();
}

答案 4 :(得分:2)

我认为你的意思是:

using (var x = new Y(params))
{
}

在这两种情况下?然后明显的区别是 x 的范围。在第二种情况下,您可以在catch子句中访问 x 。在第一种情况下,你不能。

我也会借此机会提醒你不要“处理”一个例外情况,除非你能真正做些什么。这包括记录异常,这是可以的,除非您正在操作的环境为您执行日志记录(默认情况下是ASP.NET 2.0)。

答案 5 :(得分:2)

如上所述,只有第一种方法会捕获IDisposable对象初始化中的异常,并且将使对象具有catch块的范围。

此外,catch和finally块的操作顺序将根据其嵌套进行翻转。请看以下示例:

public class MyDisposable : IDisposable
{
    public void Dispose()
    {
        Console.WriteLine("In Dispose");
    }

    public static void MethodOne()
    {
        Console.WriteLine("Method One");
        using (MyDisposable disposable = new MyDisposable())
        {
            try
            {
                throw new Exception();
            }
            catch (Exception ex)
            {
                Console.WriteLine("In catch");
            }
        }
    }

    public static void MethodTwo()
    {
        Console.WriteLine("Method Two");
        try
        {
            using (MyDisposable disposable = new MyDisposable())
            {
                throw new Exception();
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine("In catch");
        }
    }

    public static void Main()
    {
        MethodOne();
        MethodTwo();
    }
}

这将打印:

Method One
In catch
In Dispose
Method Two
In Dispose
In catch

答案 6 :(得分:1)

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

using (Font font1 = new Font("Arial", 10.0f)) 
{
    byte charset = font1.GdiCharSet;
}

相同
{
  Font font1 = new Font("Arial", 10.0f);
  try
  {
    byte charset = font1.GdiCharSet;
  }
  finally
  {
    if (font1 != null)
      ((IDisposable)font1).Dispose();
  }
}