为什么 IEnumerator<T>继承自 IDisposable 而非通用 IEnumerator 不? [英] Why does IEnumerator&lt;T&gt; inherit from IDisposable while the non-generic IEnumerator does not?

查看:32
本文介绍了为什么 IEnumerator<T>继承自 IDisposable 而非通用 IEnumerator 不?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我注意到泛型 IEnumerator 继承自 IDisposable,但非泛型接口 IEnumerator 没有.为什么要这样设计?

I noticed that the generic IEnumerator<T> inherits from IDisposable, but the non-generic interface IEnumerator does not. Why is it designed in this way?

通常,我们使用 foreach 语句来遍历 IEnumerator 实例.foreach 生成的代码实际上有 try-finally 块,它在 finally 中调用 Dispose().

Usually, we use foreach statement to go through a IEnumerator<T> instance. The generated code of foreach actually has try-finally block that invokes Dispose() in finally.

推荐答案

基本上这是一个疏忽.在 C# 1.0 中,foreach never 调用 Dispose 1.使用 C# 1.2(在 VS2003 中引入 - 奇怪的是没有 1.1)foreach 开始检查 finally 块中的迭代器是否实现了 IDisposable- 他们不得不这样做,因为追溯性地使 IEnumerator 扩展 IDisposable 会破坏每个人对 IEnumerator 的实现.如果他们发现 foreach 首先处理迭代器很有用,我敢肯定 IEnumerator 会扩展 IDisposable.

Basically it was an oversight. In C# 1.0, foreach never called Dispose 1. With C# 1.2 (introduced in VS2003 - there's no 1.1, bizarrely) foreach began to check in the finally block whether or not the iterator implemented IDisposable - they had to do it that way, because retrospectively making IEnumerator extend IDisposable would have broken everyone's implementation of IEnumerator. If they'd worked out that it's useful for foreach to dispose of iterators in the first place, I'm sure IEnumerator would have extended IDisposable.

然而,当 C# 2.0 和 .NET 2.0 出现时,他们有了新的机会 - 新界面,新继承.让接口扩展 IDisposable 更有意义,这样你就不需要在 finally 块中进行执行时检查,现在编译器知道迭代器是否是 IEnumerator<T> 它可以发出对 Dispose 的无条件调用.

When C# 2.0 and .NET 2.0 came out, however, they had a fresh opportunity - new interface, new inheritance. It makes much more sense to have the interface extend IDisposable so that you don't need an execution-time check in the finally block, and now the compiler knows that if the iterator is an IEnumerator<T> it can emit an unconditional call to Dispose.

在迭代结束时调用 Dispose 非常有用(不管它结束).这意味着迭代器可以保留资源 - 这使得它可以逐行读取文件.迭代器块生成 Dispose 实现,确保与迭代器的当前执行点"相关的任何 finally 块在它被释放时被执行——这样你就可以编写正常的代码在迭代器和清理中应该适当地发生.

It's incredibly useful for Dispose to be called at the end of iteration (however it ends). It means the iterator can hold on to resources - which makes it feasible for it to, say, read a file line by line. Iterator blocks generate Dispose implementations which make sure that any finally blocks relevant to the "current point of execution" of the iterator are executed when it's disposed - so you can write normal code within the iterator and clean-up should happen appropriately.

1 回顾 1.0 规范,它已经被指定了.我还没有能够验证之前的声明,即 1.0 实现没有调用 Dispose.

1 Looking back at the 1.0 spec, it was already specified. I haven't yet been able to verify this earlier statement that the 1.0 implementation didn't call Dispose.

这篇关于为什么 IEnumerator<T>继承自 IDisposable 而非通用 IEnumerator 不?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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