В основном это был недосмотр. В C # 1.0 foreach
никогда не вызывал Dispose
1. С C # 1.2 (представленный в VS2003 - нет 1.1, как ни странно) foreach
начал проверять в блоке finally
, реализован ли итератор IDisposable
- они должны были сделать это таким образом, потому что ретроспективно выполнение IEnumerator
extension IDisposable
нарушило бы реализацию каждого IEnumerator
. Если бы они выяснили, что foreach
полезно избавляться от итераторов в первую очередь, я уверен, что IEnumerator
расширил бы IDisposable
.
Однако, когда вышли C # 2.0 и .NET 2.0, у них появилась новая возможность - новый интерфейс, новое наследование. Гораздо больше смысла расширять интерфейс IDisposable
, чтобы вам не требовалась проверка времени выполнения в блоке finally, и теперь компилятор знает, что если итератором является IEnumerator<T>
, он может послать безусловный вызов Dispose
.
РЕДАКТИРОВАТЬ: невероятно полезно, чтобы Dispose
вызывался в конце итерации (однако она заканчивается). Это означает, что итератор может удерживать ресурсы, что позволяет ему, скажем, читать файл построчно. Блоки итератора генерируют Dispose
реализаций, которые гарантируют, что любые finally
блоки, относящиеся к «текущей точке выполнения» итератора, выполняются, когда он удаляется, поэтому вы можете написать нормальный код внутри итератора, и очистка должна происходить соответствующим образом.
1 Если посмотреть на спецификацию 1.0, она уже была указана. Я еще не смог проверить это более раннее утверждение, что реализация 1.0 не вызывала Dispose
.
person
Jon Skeet
schedule
24.10.2008