13

我知道我之前问过一个相关的问题。我只是有了另一个想法。

using (SqlConnection conn = new SqlConnection('blah blah'))
{
    using(SqlCommand cmd = new SqlCommand(sqlStatement, conn))
    {
        conn.open();

        // *** do I need to put this in using as well? ***
        SqlDataReader dr = cmd.ExecuteReader() 
        {
            While(dr.Read())
            {
                //read here
            }
        }
    }
}

论点是:由于SqlDataReader dr对象不是像连接或命令对象那样的新对象,它只是指向cmd.ExecuteReader()方法的引用,我是否需要将阅读器放在using. (现在根据我以前的帖子,我的理解是任何使用的对象都IDisposable需要放在 a 中using,并且SQLDataReader继承自IDisposable,所以我需要把它放在。我的判断是否正确?)我只是很困惑,因为它不是一个新对象,在处理一个只是指向命令的引用指针的对象时会导致任何问题吗?

非常感谢

4

2 回答 2

30

我认为你错了。dr是对返回的对象的引用,这将cmd.ExecuteReader是一个新对象。在您的示例中,什么都不会处理dr,所以是的,它需要在 a 中using,或者手动处理。

您对需要在 a 中的实现者的判断IDisposable正确的。他们将在外面正常工作。语句只是 a 的语法糖。实现的东西应该调用,因为它们发出信号,表明它们需要以确定性的方式处理某些状态。usingusingtry ... finallyIDisposableDispose

请注意,如果您不调用Dispose,它并不总是有问题。一些对象还实现了终结器,它将由垃圾收集器触发。如果他们不实现终结器,他们可能会留下未回收的非托管内存。在您的应用程序关闭之前,这将保持未回收状态。所有托管内存最终都会被回收,除非它不符合垃圾回收条件。

重写:

using (SqlConnection conn = new SqlConnection('blah blah')) 
using(SqlCommand cmd = new SqlCommand(sqlStatement, conn)) 
{
   conn.open(); 
   using (SqlDataReader dr = cmd.ExecuteReader())
   { 
        while (dr.Read()) 
        { 
           //read here 
        } 
   } 
} 
于 2010-08-02T10:18:08.773 回答
2

您应该将数据读取器包装在 using 语句中,因为 ExecuteReader 方法正在创建一个新的数据读取器实例,该实例也应该被处理掉。

于 2010-08-02T10:17:23.517 回答