В основному це був недогляд. У C # 1.0 foreach
ніколи не називався Dispose
1 . З C # 1.2 (представлений у VS2003 - 1.1, химерно не існує) foreach
почав перевіряти в finally
блоці, чи реалізований ітератор IDisposable
- вони повинні були зробити це таким чином, оскільки ретроспективне IEnumerator
розширення IDisposable
порушило б реалізацію всіх IEnumerator
. Якби вони з’ясували, що foreach
спочатку корисно розпоряджатися ітераторами, я впевнений, IEnumerator
розширив би це IDisposable
.
Однак, коли вийшли C # 2.0 та .NET 2.0, у них з’явилася нова можливість - новий інтерфейс, нове успадкування. Набагато більше сенсу мати розширення інтерфейсу, IDisposable
так що вам не потрібна перевірка часу виконання в блоці нарешті, і тепер компілятор знає, що якщо ітератор є, IEnumerator<T>
він може видавати безумовний виклик Dispose
.
РЕДАГУВАТИ: Це неймовірно корисно для того, Dispose
щоб його викликали в кінці ітерації (однак вона закінчується). Це означає, що ітератор може триматися на ресурсах - що робить можливим, наприклад, читати файл, рядок за рядком. Блоки ітератора генерують Dispose
реалізації, які гарантують, що будь-які finally
блоки, що мають відношення до "поточної точки виконання" ітератора, виконуються, коли він утилізується - так що ви можете написати звичайний код в ітераторі, і очищення має відбутися належним чином.
1 Оглядаючись на специфікацію 1.0, вона вже була вказана. Я ще не зміг перевірити це попереднє твердження, що реалізація 1.0 не викликала Dispose
.
IEnumerable.GetEnumerator
(не-загальний) будеIDisposable
таким же?