问题 在代码中使用'“using”关键字时,我应该在哪里捕获异常?


哪一个结构更好?

class Program
{
    static void Main(string[] args)
    {
        try
        {
            using (Foo f = new Foo())
            {
                //some commands that potentially produce exceptions.
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

要么...

class Program
{
    static void Main(string[] args)
    {

        using (Foo f = new Foo())
        {
            try
            {
                //some commands that potentially produce exceptions.
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

    }
}

6453
2017-08-03 10:13


起源

stackoverflow.com/questions/911626/... - Kashif
如果您只想记录从Main抛出的任何异常,请使用Option1。如果你需要在处理之前访问异常处理程序中的f,你需要使用Option2 - 否则f将超出范围。 - 杜佩,投票结束。 - Gishu


答案:


要么是好的,取决于你将要捕获的内容。如果你需要使用 f 在你的catch中,它需要在using语句中。但是在你的例子中没有区别。

编辑: 正如其他地方所指出的那样,它还取决于您是否尝试在使用或包含using语句中的对象创建后捕获块中生成的异常。如果它在使用后的块中,那么它就像我描述的那样。如果要捕获由...生成的异常 Foo f = new Foo() 那么你需要使用第一种方法。


7
2017-08-03 10:16



我不同意阅读我的答案中粘贴的链接 - Pranay Rana
如果我使用opt 2和异常获取throw表单构造函数该怎么办? - Pranay Rana
@June R.我添加了一些编辑,谢谢。通用问题的问题是规则总是有例外。在不知道实际用法的情况下,我认为不可能说一个比另一个更正确。真正的答案取决于你在做什么。 - btlog


在性能方面,我认为这不重要。但是有一点点不同;在第二个例子中, f 在异常处理程序中仍然可用,而在第一个处理程序中,它已超出范围。相反,在第一个例子中,例外 Foo 构造函数以及它的 Dispose 方法将被捕获,而在第二,他们不会。

可能是也可能不是你想要的。


2
2017-08-03 10:17



我不同意阅读我的答案中粘贴的链接 - Pranay Rana
如果我使用opt 2和异常获取throw表单构造函数该怎么办? - Pranay Rana
编辑澄清。 - tdammers


查看此帖子以更好地理解: http://www.ruchitsurati.net/index.php/2010/07/28/understanding-%E2%80%98using%E2%80%99-block-in-c/

另请阅读此问题的答案: 捕获在Using块的目标对象的构造函数中抛出的异常

第一个是下一个

class Program
{
    static void Main(string[] args)
    {
        try
        {
            using (Foo f = new Foo())
            {
                //some commands that potentially produce exceptions.
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

因为如果你看到这个try和catch块的IL代码没有包装对象的inialization。


1
2017-08-03 10:16





第一个更好,因为它将捕获在处置过程中抛出的任何异常。当然,在处理时你不应该抛出任何异常,但事情会发生。


1
2017-08-03 10:21



是的,我建议.... - Pranay Rana
类似地,它还将捕获Foo构造函数中抛出的异常,而第二种形式则不会。 - Christopher McAtackney


第一个是更好的一个。如果有任何异常,它会抓住。

 try
    {
        using (Foo f = new Foo())
        {
            //some commands that potentially produce exceptions.
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }

使用的概念是它将处理在using.i.e中创建的对象,它自动调用IDispose方法。基于要求使用 运用


1
2017-08-03 10:25





使用就是

Foo f = null;
try
{
   f = new Foo();
}
finally
{
   if (f is IDisposable)
       f.Dispose();
}

看到你可以实现捕获这样的异常:

Foo f = null;
try
{
   f = new Foo();
}
catch (Exception ex)
{
    // handle exception
}
finally
{
   if (f is IDisposable)
       f.Dispose();
}

1
2017-08-03 10:38



当f.Dispose()可能发出其他异常时,它也必须被try-catch包围。 - xport