C# 如何捕获带有“异常”的异常;使用;在C中#
鉴于此代码:C# 如何捕获带有“异常”的异常;使用;在C中#,c#,sql,ado.net,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())
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块的替代品。我知道使用不会捕获异常。那么这是如何替代的呢?使用语句与异常无关。使用块只是确保在使用块中的对象退出该块时对其调用Dispose。即:
using(SqlConnection conn = new SqlConnection(conStr))
{
//use conn
}//Dispose is called here on conn.
如果打开连接引发异常(或该块中的任何其他异常),它仍然会冒泡到顶部,并且与任何其他未处理的异常一样。
使用
不是为了捕获异常而设计的;它旨在为您提供一种简单的方法,将try
/最终
包裹在需要处置的对象周围。如果您需要捕获并处理异常,那么您需要将其扩展为完整的try
/捕获
/最后
或在整个事件周围放置一个包含try
/捕获
要回答您的编辑(是否使用替换尝试/catch
/最后
?),则不是。在大多数情况下,当使用一次性资源时,您不会在那里处理异常,因为通常情况下,您无法做任何有用的事情。因此,它提供了一种方便的方法,可以确保资源得到清理,而不管您尝试执行的操作是否有效
通常,处理可支配资源的代码的工作级别太低,无法决定失败时的正确操作,因此将异常传播给调用方,调用方可以决定要采取的操作(例如重试、失败、日志等)。
您倾向于使用带有一次性资源的catch
块的唯一地方是,如果您要转换异常(我假设,这就是您的数据访问层正在做的事情)。如果您想捕获异常,您可能应该返回使用try/catch/finally。只需将.Dispose()调用放在finally块中。将所有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
}
您仍然可以像以前一样捕获(或忽略)异常。关键是,您不再需要担心如何处理数据库连接
也就是说,如果您的应用程序出于某些其他原因(例如,日志记录)需要捕获异常,请继续,但如果您只想处理数据库连接,则不再需要这样做:
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
}
语法上的糖是什么
var cmd = new SqlCommand("SELECT * FROM Customers");
try
{
cmd.CommandTimeout = 60000;
...
}
finally
{
if (cmd != null)
cmd.Dispose();
}
因此,当人们告诉你“使用”是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();
}
放入一个try catch
块中,使用块/s来阻止。用于对象处置的隐式finally
语句将在外部块catch
语句及其内容之前执行。try/catch/finally并在我的finally块中调用dispose如何更好?Erik,为什么要在finally块中调用dispose?什么时候可以使用using语句?如果使用finally块,那么必须在try块之外声明对象……在内部,这与using语句将生成的IL相同。一开始我想不出那个解决方案,试着在“使用”偏执中写“try”子句,然后当然编译器说wtf正在做:D。然后到了第页。他说:“哦,我的天哪,我怎么能不那样想呢?”他可以把使用包装成一个try/catch块。如果捕获到错误,在输入catch之前将调用Dispose(如果存在)。这是真的,但是您还有一个缩进级别,using语句不再那么方便了。我更喜欢用try/catch/finally来处理所有的事情(但这是一个很小的风格)。但是即使使用简单的错误处理,也可以很容易地编写代码,看起来它调用了Dispose()
,但在某些情况下失败了<代码>使用()
至少可以确保正确地清理它,即使它几乎不可能进行细粒度异常处理。这很有趣。我想知道你是否要在这里插入你的头:)如果在try块中创建cmd,你不能在finally块中调用dispose。这与其他答案有什么不同,例如Chuck Conway的答案?它解释了隐式“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();
}