【问题标题】:Does foreach automatically call Dispose?foreach 会自动调用 Dispose 吗?
【发布时间】:2011-02-13 04:15:48
【问题描述】:

在 C# 中,foreach 会自动对任何实现 IDisposable 的对象调用 Dispose 吗?

http://msdn.microsoft.com/en-us/library/aa664754(v=vs.71).aspx 似乎表明确实如此:

*否则,集合表达式为实现System.IEnumerable的类型,foreach语句的扩展为: 复制

IEnumerator enumerator = 
        ((System.Collections.IEnumerable)(collection)).GetEnumerator();
try {
   while (enumerator.MoveNext()) {
      ElementType element = (ElementType)enumerator.Current;
      statement;
   }
}
finally {
   IDisposable disposable = enumerator as System.IDisposable;
   if (disposable != null) disposable.Dispose();
}

【问题讨论】:

    标签: c# foreach idisposable


    【解决方案1】:

    是的,如果 foreach 实现了 IDisposable,它将在枚举器上调用 Dispose()。

    【讨论】:

    • 如果它令人困惑,它看起来像是对枚举器本身调用 dispose,而不是枚举中的项目。如果它在每个项目上调用它,那可能会破坏很多场景,并且很难使异常安全:)
    • foreach 方法只会对从GetEnumerator 返回的对象执行运行时检查,如果该方法的返回类型是接口,则查看它是否实现了IDisposable。否则,编译器将在编译时决定是否调用Dispose。特别是,如果返回类型是一个没有实现IDisposable的可继承类,则返回的对象将不会被释放即使它实现了IDisposable
    • @supercat,您能否进一步解释一下,以利于我的理解(也许还有其他人 ;-)。我可以从文档 (msdn.microsoft.com/en-us/library/aa664754%28v=vs.71%29.aspx) 中收集到的是,当 E enumeratorfinal class 并且 not 实现 IDisposable 时,可以优化实现并且“在这种情况下,实现可以安全地优化整个 finally 子句。” (= 没有打电话给.Dispose())。但是我看不出E enumerator确实实现IDisposable.Dispose()没有被调用的任何可能性。
    • @BatteryBackupUnit:我想我在上面说错了。我主要使用 VB.NET,它在许多方面与 C# 相似,其 For Each 的行为与描述的一样。
    【解决方案2】:

    这个问题/答案措辞不当。

    不清楚问题是否是:

    问:“foreach 是否在移动到下一个之前处理枚举器返回的对象?”

    A:答案当然是,NO。它除了提供一种方便的方法来为枚举中的每个对象运行一次代码之外什么都不做。

    或者是否意味着:

    问:“在底层,foreach 使用了一个可枚举的对象。即使在迭代器块中存在异常,它是否会在调用 foreach 后被释放?”

    A:答案是(仍然很明显)是的!由于语法不提供对枚举器的访问权限,因此它有责任处置它。

    第二个问题的答案是混乱出现的地方,因为人们听说 foreach 扩展为带有 try/finally 块的 while 块。 finally 的目的是确保枚举器在实现 IDisposable 时被释放。

    如果您需要自己查看:See it in action here

    希望这有助于澄清! ;)

    【讨论】:

    • “foreach 使用可枚举对象”是指“foreach 使用可枚举集合给出的枚举器”。
    • 我学到了一个艰难的方法,我仍然必须处理集合(可枚举):(
    猜你喜欢
    • 1970-01-01
    • 2013-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-17
    • 1970-01-01
    • 2014-02-15
    • 1970-01-01
    相关资源
    最近更新 更多