foreach会自动调用Dispose吗?

28 浏览
0 Comments

foreach会自动调用Dispose吗?

在C#中,对于实现IDisposable接口的任何对象,foreach语句会自动调用Dispose方法吗?根据http://msdn.microsoft.com/en-us/library/aa664754(v=vs.71).aspx,似乎是这样的:\n*否则,集合表达式是实现了System.IEnumerable接口的类型,foreach语句的展开形式如下:\n复制\n

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();
}

0
0 Comments

这个问题的出现主要是由于问题和回答的措辞不清晰。不清楚提问的问题是:

Q: "foreach是否在移动到下一个对象之前自动调用Dispose方法来释放对象?"

A: 当然,答案是否定的。foreach除了提供一种方便的方式来遍历枚举中的每个对象之外,不会进行任何操作。

或者是否指的是:

Q: "在底层,foreach使用一个可枚举对象。即使在迭代器块中出现异常,调用foreach后,这个对象是否会被释放?"

A: 答案(显然)是肯定的!因为语法不允许直接访问枚举器,所以foreach有责任对其进行释放。

第二个问题的答案是导致混淆的原因,因为人们听说foreach会被展开为一个带有try/finally块的while循环。这个finally块的目的是确保如果枚举器实现了IDisposable接口,则对其进行释放。

如果你想亲自看看,请点击链接在这里查看

希望这有助于澄清! 😉

在 "foreach使用一个可枚举对象" 这句话中,你的意思是 "foreach使用可枚举集合给出的枚举器"。

我吃了个大亏,我仍然需要释放集合(可枚举对象):(

0
0 Comments

foreach循环在遍历集合时,如果枚举器实现了IDisposable接口,会自动调用Dispose()方法进行资源释放。这样设计的原因是为了保证异常安全性,如果在遍历过程中对每个元素都调用Dispose()方法,可能会破坏很多场景,并且非常难以保证异常安全。

需要注意的是,foreach方法只会在返回类型为接口时,对从GetEnumerator方法返回的对象进行运行时检查,判断它是否实现了IDisposable接口。否则,编译器会在编译时决定是否调用Dispose()方法。特别地,如果返回类型是一个不实现IDisposable接口的可继承类,即使它实际上实现了IDisposable接口,返回的对象也不会被释放。

如果在使用过程中发现foreach循环没有调用Dispose()方法,可能是因为枚举器是一个final类并且没有实现IDisposable接口,这时编译器可以对其进行优化,省略整个finally子句,从而不调用Dispose()方法。但是如果枚举器实现了IDisposable接口,却没有调用Dispose()方法,目前还没有找到可能的情况。

以上是对问题的解释,希望对你理解有所帮助。

0