如何在C#中使用“using”捕获异常

时间:2009-02-05 22:34:25

标签: c# sql ado.net

鉴于此代码:

using (var conn = new SqlConnection("..."))
{
    conn.Open();
    using (var cmd = conn.CreateCommand())
    {
        cmd.CommandText = "...";
        using (var reader = cmd.ExecuteReader())
        {
            while (reader.Read())
            {
                // ...
            }
        }
    }
}

我习惯为我的数据访问编写try / catch / finally块,但是,我正在接触“使用”这似乎是一种更简单的方法。但是,我正在试图找出如何捕获可能发生的异常。

你能举个例子说明你如何捕捉异常吗?

已编辑添加:

我被引导相信“使用”是我的try / catch / finally块的替代品。我知道使用不会捕获异常。那怎么替代呢?

7 个答案:

答案 0 :(得分:57)

using并非旨在捕获异常;它旨在为您提供一种简单的方法,将try / finally包裹在需要处理的对象周围。如果您需要捕获和处理异常,那么您需要将其扩展为完整的try / catch / finally或将其包含try / {{1}围绕整个事情。


要回答您的修改(catch替换using / try / catch?),请注意,不是。大多数情况下,当使用一次性资源时,您不会在那里处理异常,因为通常没有什么用处可以做。因此,它提供了一种方便的方法来确保资源被清理,无论您尝试做什么工作与否。

通常,处理可支配资源的代码工作的级别太低,无法确定正确操作失败的原因,因此会将异常传播给调用者,调用者可以决定要采取的操作(例如,重试,失败,日志等)。 你倾向于使用带有可支配资源的finally块的唯一地方是你要翻译异常(我假设你的数据访问层在做什么)。

答案 1 :(得分:12)

using (var cmd = new SqlCommand("SELECT * FROM Customers"))
{
    cmd.CommandTimeout = 60000;
    ...
}

的语法糖
var cmd = new SqlCommand("SELECT * FROM Customers");
try
{
    cmd.CommandTimeout = 60000;
    ...
}
finally
{
    if (cmd != null)
        cmd.Dispose();
}

所以当人们告诉你“使用”是try / catch /的替代品时,他们暗示你应该使用长手形式但是加入你的catch块:

var cmd = new SqlCommand("SELECT * FROM Customers");
try
{
    cmd.CommandTimeout = 60000;
    ...
}
catch (Exception ex)
{
    ...//your stuff here
}
finally
{
    if (cmd != null)
        cmd.Dispose();
}

答案 2 :(得分:11)

将所有using语句包装到try / catch中。像其他人一样,使用的是清理实现IDisposable接口的类

try
{

 using (var conn = new SqlConnection("..."))
 {
    conn.Open();
    using (var cmd = conn.CreateCommand())
    {
        cmd.CommandText = "...";
        using (var reader = cmd.ExecuteReader())
        {
            while (reader.Read())
            {
                // ...
            }
        }
    }
 }
}
catch(Exception ex)
{
//Handle, log, rethrow exception
}

答案 3 :(得分:7)

如果你想捕获异常,你可能应该回到使用try / catch / finally。只需将.Dispose()调用放在finally块中。

答案 4 :(得分:6)

使用语句与异常无关。使用块只是确保在使用块中的对象上调用Dispose,当它退出该块时。即:

using(SqlConnection conn = new SqlConnection(conStr))
{
   //use conn
}//Dispose is called here on conn.

如果打开连接会引发异常(或该块中的任何其他内容),它仍然会冒泡到顶部,就像任何其他无法处理的异常一样。

答案 5 :(得分:3)

您仍然可以像以前一样完全捕获(或忽略)异常。关键是你不再需要担心处理数据库连接。

即,如果您的应用程序要求您因某些其他原因(例如,日志记录)捕获异常,请继续,但如果您只想处置数据库连接,则不再需要这样做:

using (SqlConnection conn = new SqlConnection(...))
{
    // do your db work here
    // whatever happens the connection will be safely disposed
}

如果由于其他原因想要捕获异常,您仍然可以这样做:

try
{
    using (SqlConnection conn = new SqlConnection(...))
    {
        // do your db work here
        // whatever happens the connection will be safely disposed
    }
}
catch (Exception ex)
{
    // do your stuff here (eg, logging)
    // nb: the connection will already have been disposed at this point
}
finally
{
    // if you need it
}

答案 6 :(得分:0)

try catch块放入一个using块中。他们专用于对象处置的隐式finally语句将在外部块catch语句及其内容之前执行。