C# Dispose与迭代器块

C# Dispose与迭代器块,c#,ienumerable,dispose,yield-return,ienumerator,C#,Ienumerable,Dispose,Yield Return,Ienumerator,这两个问题几乎回答了我自己的问题,但并不完全如此。考虑到这些问题的后续问题。 我知道foreach循环在处理完枚举数后将Dispose 我的问题是: 如果所讨论的枚举数实际上是IEnumerable类的c#迭代器块(即GetEnumerator()/yield),该类本身实现了IDisposable,那么我是否可以确定对象本身将被释放?或者我是否需要使用块在内部显式调用GetEnumerator()/MoveNext()/Current 编辑:演示@JonSkeet的答案 编辑#2:基于

这两个问题几乎回答了我自己的问题,但并不完全如此。考虑到这些问题的后续问题。

我知道
foreach
循环在处理完枚举数后将
Dispose

我的问题是:

如果所讨论的枚举数实际上是
IEnumerable
类的c#迭代器块(即
GetEnumerator()/yield
),该类本身实现了
IDisposable
,那么我是否可以确定对象本身将被释放?或者我是否需要使用块在
内部显式调用
GetEnumerator()/MoveNext()/Current

编辑:演示@JonSkeet的答案


编辑#2:基于@JonSkeet的评论,展示了理想的用法。迭代器块负责所需资源的生存期,而不是可枚举对象本身。这样,如果需要,可以多次枚举可枚举项--每个可枚举项都有自己的资源可使用。

foreach
在迭代器上调用
Dispose
,而不管该迭代器的实现如何。不管它是否是用迭代器块创建的,它的
Dispose
方法都会被调用

这就是接口的全部要点,比如
IDisposable
。您不需要关心底层实现是什么。它总是处理一切。他们选择如何处理这个电话取决于他们自己


对于迭代器块生成的
IEnumerable
(而不是
IEnumerator
),它永远不会实现
IDisposable
,因此无法处理。如果您有一个实现了
IEnumerable
IDisposable
的自定义对象(而不是迭代器块),则在
foreach
中使用时将不会处理该对象。只有通过
GetEnumerator
创建的
IEnumerator
将被删除。

如果您想处理
IEnumerable
,您需要自己使用
语句(或手动尝试/最终)处理
foreach
循环不会自动处理
IEnumerable
,只处理它返回的迭代器

因此,您需要:

using (var enumerable = new MyEnumerable())
{
    foreach (var element in enumerable)
    {
        ...
    }
}

无论
MyEnumerable
是使用迭代器块还是其他代码实现
IEnumerable
,都没有任何区别。

您可以发布SSCCE吗?(这样做并运行它可能会回答这个问题。)我不太明白这个问题:使用枚举器的任何操作都不会导致它所属的集合对象被释放。调用方无法告诉迭代器方法是如何实现的。另一种.NET语言可能甚至不知道这个概念。您是否在问,如果在
IEnumerable上执行
foreach
,其中T:IEnumerable、IDisposable
将处理
U
类型的对象?当然不是,为什么会这样?如果我列举了一组打开的套接字,那么这些套接字是否应该自动关闭?不太清楚您的意思-您是否试图处理通过迭代器返回的每个对象?@CSJ它没有实现
IDisposable
,也没有
dispose
方法,因此无法处理它
IEnumerator
扩展了
IDisposable
,而不是
IEnumerable
。我很害怕。另一种方法是在迭代器块本身退出之前进行任何清理(例如,直接在
yield break
前面调用
this.Dispose()
)@CSJ:您必须使用(this){…}执行类似
的操作
-不要忘记,
foreach
可能不会迭代迭代器的全部内容。然而,我强烈建议你不要这样做。至少可以说,对一个序列进行迭代以处理该序列本身是非常不习惯的。这听起来是一个相当奇怪的设计开始…我明白了。似乎我更感兴趣的是构建一个枚举器,而不是一个可枚举的。@CSJ再说一次,不可能编写一个迭代器块来生成一个可一次性使用的
IEnumerable
,因此让它在迭代器块内自行处理是一个没有意义的问题。这不是唯一的障碍。它需要是一个非迭代器块
IEnumerable
。除此之外,
IEnumerator
还需要一些方法来知道是什么
IEnumerable
创建了它。这是一个潜在的可以解决的问题,但仍然是不好的做法,完全没有必要。如果您处于这种情况,请不要在
IEnumerable
@Servy中创建可支配资源,JonSkeet:非常有趣的讨论,清楚地指出了枚举器和可枚举器各自的责任。所以这是一个要避免的参考示例。实际上,使用迭代器块生成的迭代器确实实现了dispose,但是您需要尝试\最终才能看到它@ScottChamberlain这是
IEnumerator
,而不是
IEnumerable
。差别很大。
IEnumerable
没有dispose方法。啊,没有找到。很抱歉