使用IDisposable时放置try / catch的位置

时间:2011-10-27 06:14:07

标签: c# try-catch idisposable

我刚建议将整个using块放在try内,否则using范围将阻止异常被捕获。但是,如果抛出异常,是否会阻止using正确处理其资源?如果我有下面的代码,我应该在哪里放置try块?

using (connSQL = new SqlConnection(strConn)) 
{
    connSQL.Open();
    using (SqlCommand commSQL = new SqlCommand(strPreparedStatement, connSQL)) 
    {
        if (sqlParameters != null)
        {
            for (int i = sqlParameters.GetLowerBound(0); i <= sqlParameters.GetUpperBound(0); i++)
            {
                commSQL.Parameters.Add(sqlParameters[i]);
            }
        }
        drSQL = commSQL.ExecuteReader();
        dtReturn.Load(drSQL);

        commSQL.Parameters.Clear();
    }
}

在此应用程序中,确保与数据库的连接不会因异常而开始累积更为重要。

3 个答案:

答案 0 :(得分:9)

using语句已经阻止了连接的累积 - 它通过调用{{1}有效地成为try / finally块来为您做清理工作。在Dispose块中。如果您想要finally / try阻止,您可以将其置于内部或外部 - 但您确定它不应该处于更高级别吗?您实际上期望处理例外吗?

顺便说一句,目前还不清楚为什么要在命令即将被处理时清除命令中的参数......

我鼓励你在catch语句中声明变量,这样你就不会试图在块之外读取它们了:

using

通常,您希望尽可能缩小范围。哦,您的using (SqlConnection connSQL = new SqlConnection(strConn)) { 也应该在SqlDataReader声明中。无论如何,当你关闭连接和命令时,它可能无关紧要,但我会把它作为一个原则点 - 它实现using,所以你应该处理它。

哦,你对IDisposable进行迭代的方式目前相当长。 sqlParameters使其变得更简单,即使它没有使用foreach,除非我有理由相信它不是一个“简单”数组。

所以,我的等效代码看起来像这样:

for (int i = 0; i < sqlParameters.Length; i++)

答案 1 :(得分:2)

您需要将数据读取器包装在using语句中,因为它是一次性资源:

using (var connSQL = new SqlConnection(strConn)) 
using (var commSQL = connSQL.CreateCommand()) 
{
    connSQL.Open();
    commSQL.CommandText = strPreparedStatement;
    if (sqlParameters != null)
    {
        for (int i = sqlParameters.GetLowerBound(0); i <= sqlParameters.GetUpperBound(0); i++)
        {
            commSQL.Parameters.Add(sqlParameters[i]);
        }
    }
    using (var drSQL = commSQL.ExecuteReader())
    {
        dtReturn.Load(drSQL);
    }
}

我还将连接,命令和数据读取器对象本地定义到此块范围中。

try/finally语句而言,您不再需要它,因为using语句确保即使在异常情况下也会调用Dispose方法。这种用于sql连接和命令的方法可以确保正确地释放它们。

答案 2 :(得分:1)

没有必要放try catch因为using隐式实现它,实际上它最后使用try并确定它会处理对象。

这是关于try catch和使用的MSDN using Sample

{
  Font font1 = new Font("Arial", 10.0f);
  try
  {
    byte charset = font1.GdiCharSet;
  }
  finally
  {
    if (font1 != null)
      ((IDisposable)font1).Dispose();
  }
}

等于:

using (Font font3 = new Font("Arial", 10.0f),
            font4 = new Font("Arial", 10.0f))
{
    // Use font3 and font4.
}