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

Gre*_*egD 32 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())
            {
                // ...
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

能否请您举例说明您如何捕捉异常?

编辑添加:

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

Gre*_*ech 58

using不是为了捕捉例外; 它旨在为您提供一种简单的方法来包裹try/ finally围绕需要处理的对象.如果你需要捕获和处理异常,那么你需要将它扩展为一个完整的try/ catch/ finally或放置一个包含try/ catch围绕整个事物.


要回答你的编辑(是//?using的替代品),那么不,它不是.大多数情况下,当使用一次性资源时,您不会在那里处理异常,因为通常没有什么用处可以做.因此,它提供了一种方便的方法来确保资源被清理,而不管您尝试做什么工作.trycatchfinally

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


Rog*_*ger 14

using (var cmd = new SqlCommand("SELECT * FROM Customers"))
{
    cmd.CommandTimeout = 60000;
    ...
}
Run Code Online (Sandbox Code Playgroud)

是语法糖

var cmd = new SqlCommand("SELECT * FROM Customers");
try
{
    cmd.CommandTimeout = 60000;
    ...
}
finally
{
    if (cmd != null)
        cmd.Dispose();
}
Run Code Online (Sandbox Code Playgroud)

因此,当人们告诉你"使用"是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();
}
Run Code Online (Sandbox Code Playgroud)


Chu*_*way 12

将所有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
}
Run Code Online (Sandbox Code Playgroud)


Kev*_*ghe 7

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

  • 这是真的,但是你还有一个级别的缩进,而且using语句不再那么方便了.我宁愿让一个try/catch/finally处理所有东西(但那是一个小风格的东西). (2认同)

BFr*_*ree 6

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

using(SqlConnection conn = new SqlConnection(conStr))
{
   //use conn
}//Dispose is called here on conn.
Run Code Online (Sandbox Code Playgroud)

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


Luk*_*keH 5

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

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

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

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

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
}
Run Code Online (Sandbox Code Playgroud)