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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/518292/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 06:28:51  来源:igfitidea点击:

How do you catch exceptions with "using" in C#

c#sqlado.net

提问by GregD

Given this code:

鉴于此代码:

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

I'm used to writing try/catch/finally blocks for my data access, however, I'm being exposed to "using" which seems like a much simpler method of doing this. However, I'm trying to figure out how to catch exceptions that may occur.

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

Could you please give me an example of how you'd catch exceptions?

你能给我一个例子来说明你如何捕捉异常吗?

Edited to add:

编辑添加:

I'm being led to believe that "using" is a replacement for my try/catch/finally blocks. I understand that using doesn't catch exceptions. So how is this a replacement?

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

采纳答案by Greg Beech

usingisn't designed to catch exceptions; it's designed to give you an easy way to wrap a try/finallyaround an object that needs to be disposed. If you need to catch and handle exceptions then you'll need to expand it into a full try/catch/finallyor put a containing try/catcharound the whole thing.

using不是为了捕捉异常而设计的;它的目的是给你一个简单的方法来包装一个try/finally围绕一个对象,需要处置。如果您需要捕获和处理异常,那么您需要将其扩展为完整的try/ catch/finally或在整个事物周围放置一个包含try/ catch



To answer your edit (is usinga replacement for try/catch/finally?) then no, it isn't. Most of the time when using a disposable resource you aren't going to handle the exception there and then because there's normally nothing useful you can do. So it provides a convenient way to just ensure that the resource is cleaned up irrespective of what you're trying to do works or not.

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

Typically code that deals with disposable resources is working at too low a level to decide what the correct action is on failure, so the exception is left to propagate to the caller who can decide what action to take (e.g. retry, fail, log, etc.). The only place where you'd tend to use a catchblock with a disposable resource is if you're going to translate the exception (which is, I assume, what your data access layer is doing).

通常,处理一次性资源的代码的工作级别太低,无法确定失败时的正确操作,因此将异常传播给可以决定采取什么操作(例如重试、失败、记录等)的调用者.) 您倾向于使用catch具有一次性资源的块的唯一地方是您是否要转换异常(我假设,这是您的数据访问层正在做什么)。

回答by BFree

Using statements have nothing to do with Exceptions. Using blocks just insure that Dispose is called on the object in the using block, when it exits that block. I.E:

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

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

If opening the connection raises an exception (or anything else in that block for that matter) it will still bubble to the top and will be like any other unhanded exception.

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

回答by Kevin Tighe

If you want to catch exceptions there you probably should go back to using try/catch/finally. Just put the .Dispose() calls in the finally block.

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

回答by Chuck Conway

Wrap all the using statements into a try/catch. Like everyone else has said, using is for cleaning up classes that implement the IDisposable interface

将所有 using 语句包装到 try/catch 中。就像其他人所说的, using is 用于清理实现 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
}

回答by LukeH

You can still catch (or ignore) exceptions exactly as you would have previously. The point is that you no longer need to worry about disposing of the database connection.

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

ie, If your application requires that you trap exceptions for some other reason (eg, logging) then go ahead, but you no longer need to do so if you only want to dispose of the database connection:

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

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

If you want to catch the exception for some other reason, you can still do so:

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

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
}

回答by RogueBadger

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

is syntactic sugar for

是语法糖

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

So when people are telling you that "using" is a replacement for try/catch/finally they are implying that you should use the long-hand form but add in your catch block:

因此,当人们告诉您“使用”是 try/catch/finally 的替代品时,他们暗示您应该使用长手形式但添加您的 catch 块:

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