当不使用使用,或的foreach手动调用Dispose(枚举处置) [英] Enumerator disposal when not using using, foreach or manually calling Dispose()

查看:349
本文介绍了当不使用使用,或的foreach手动调用Dispose(枚举处置)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用收益回报率来遍历一个s SqlDataReader的记录:

 的IEnumerable<阅读> GetReadings(){
使用(VAR连接=新的SqlConnection(_connectionString))
{
使用(VAR命令=新的SqlCommand(_query,连接))
{
connection.Open();
使用(VAR读卡器= Command.ExecuteReader却())
{
,而(reader.Read())
{
收益回报新阅读
{
端= reader.GetDateTime(0),
值= reader.GetDouble(1)
};
}
}
的Connection.close();
}
}
}



我然后使用此接受的答案以 ZIP许多迭代器一起:

  VAR枚举= data.Select(D =>新建
{
d.Key,
=枚举d.Value.GetEnumerator()
})了ToList()。

,而(真)
{
的foreach(VAR在普查员项)
{
如果(!item.Enumerator.MoveNext())
{
产量突破;
}

/ *剪断* /
}

/ *剪断* /
}

在上述方法中,枚举的的Dispose()不显式调用,因为他们不是一个使用的foreach 语句中使用,将底层迭代器保持在打开状态?在我的情况以开放的的SqlConnection



我应该叫的Dispose()的普查员,以确保整个下游链被关闭?


解决方案

当枚举在这个迭代器,如果枚举的的Dispose()不显式调用,而不是内部使用的使用声明中,将底层迭代器保持在打开状态?




让我重新短语,质疑成一种形式,是比较容易回答




在使用的foreach 通过包含一个迭代器块<$枚举C $ C>使用语句,是设在控制离开循环的资源?




是的。




什么样的机制保证呢?




这三种:




  • A 使用语句只是一种方便的方法写了尝试,终于其中最后资源的处置。


  • 的foreach 循环的的一个方便的语法为尝试,终于,并再次,在最后要求的Dispose 就当控制离开循环中的枚举。


  • 通过迭代器模块实现生产的枚举的IDisposable 。调用的Dispose()就可以保证所有的最后迭代器块中的程序段,包括最后是来自使用语句块。





如果我避免了的foreach 循环,调用的GetEnumerator 自己,并且不叫的Dispose 的枚举,我必须保证,在最后枚举的块将跑?




不。 始终处置您的统计员。他们实施的IDisposable 的一个原因。



是,现在清楚了吗?



如果这个问题你感兴趣,那么你应该看过我在C#迭代器块的设计特点一长串。



HTTP://blogs.msdn。 COM / b / ericlippert /存档/标签/迭代器/


I'm using yield return to iterate over an SqlDataReader's records:

IEnumerable<Reading> GetReadings() {
    using (var connection = new SqlConnection(_connectionString))
    {
        using (var command = new SqlCommand(_query, connection))
        {
            connection.Open();
            using (var reader = command.ExecuteReader())
            {
                while (reader.Read())
                {
                    yield return new Reading
                    {
                        End = reader.GetDateTime(0),
                        Value = reader.GetDouble(1)
                    };
                }
            }
            connection.Close();
        }
    }
}

I'm then using an adapted version of this accepted answer to "zip" many iterators together:

   var enumerators = data.Select(d => new
   {
       d.Key,
       Enumerator = d.Value.GetEnumerator()
   }).ToList();

   while (true)
   {
       foreach (var item in enumerators)
       {
           if (!item.Enumerator.MoveNext())
           {
               yield break;
           }

           /*snip*/
       }

      /*snip*/
   }

In the method above, the enumerator's Dispose() is not explicitly called, and because they are not used within a using or foreach statement, would the underlying iterator remain in an open state? In my case with an open SqlConnection.

Should I be calling Dispose() on the enumerators to make sure the whole downstream chain is closed?

解决方案

When enumerating over this iterator, if the enumerator's Dispose() is not explicitly called, and not used within a using statement, would the underlying iterator remain in an open state?

Let me re-phrase that question into a form that is easier to answer.

When using foreach to enumerate via an iterator block that contains a using statement, are the resources disposed of when control leaves the loop?

Yes.

What mechanisms ensure this?

These three:

  • A using statement is just a convenient way to write a try-finally where the finally disposes of the resource.

  • The foreach loop is also a convenient syntax for try-finally, and again, the finally calls Dispose on the enumerator when control leaves the loop.

  • The enumerator produced by an iterator block implements IDisposable. Calling Dispose() on it ensures that all the finally blocks in the iterator block are executed, including finally blocks that come from using statements.

If I avoid the foreach loop, call GetEnumerator myself, and don't call Dispose on the enumerator, do I have a guarantee that the finally blocks of the enumerator will run?

Nope. Always dispose your enumerators. They implement IDisposable for a reason.

Is that now clear?

If this subject interests you then you should read my long series on design characteristics of iterator blocks in C#.

http://blogs.msdn.com/b/ericlippert/archive/tags/iterators/

这篇关于当不使用使用,或的foreach手动调用Dispose(枚举处置)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆