В основном это был контроль. В 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>
, это может испустить безусловный вызов к [1 113].
РЕДАКТИРОВАНИЕ: для [1 114] невероятно полезно быть названным в конце повторения (однако, это заканчивается). Это означает, что итератор может держаться за ресурсы - который делает выполнимым для него, скажем, считать файл линию за линией. Блоки итератора генерируют Dispose
реализации, которые удостоверяются, что любой finally
блоки, относящиеся к "текущей точке выполнения" итератора, выполняются, когда это расположило - таким образом, можно записать нормальный код в итераторе, и очистка должна произойти соответственно.
<глоток> 1 глоток> Оглядывающийся назад на 1,0 спецификации, это было уже определено. Я еще не был в состоянии проверить этот более ранний оператор, который 1,0 реализации не назвали Dispose
.
IEnumerable< T> не наследовал IDisposable. IEnumerator< T> действительно наследовал IDisposable однако, тогда как неуниверсальный IEnumerator не делает. Даже когда Вы используете foreach для неуниверсального IEnumerable (который возвращает IEnumerator), компилятор будет все еще генерировать чек для IDisposable, и вызов Располагают (), если перечислитель реализует интерфейс.
я предполагаю универсальный Enumerator< T> наследовался IDisposable, таким образом, не должно быть типа-выполнения-check—, это может просто идти вперед, и вызов Располагают (), который должен иметь лучшую производительность, так как это может быть, вероятно, быть оптимизированным далеко, если перечислитель имеет пустое, Располагают () метод.
IEnumerable' наследовали IDisposing? Согласно отражателю.NET или MSDN. Вы уверены, что не путаете его с IEnumerator? Это использует IDisposing потому что это только для перечисления набора и не предназначенное для долговечности.
Немного трудно, чтобы быть категоричным на этом, если Вам не удается получить ответ от AndersH самостоятельно или кого-то близко к нему.
Однако мое предположение - то, что это касается ключевого слова "урожая", которое было представлено в C# одновременно. При рассмотрении кода, сгенерированного компилятором, когда "возврат урожая x" будет использоваться, Вы будете видеть метод, обернутый в классе помощника, который реализует IEnumerator; наличие убывания IEnumerator от IDisposable гарантирует, что может вымыться, когда перечисление завершено.
IIRC Все это о наличии IEnumerable<T>
и IEnumerable
является результатом IEnumerable
шаблонный материал.Net's предшествования. Я подозреваю, что Ваш вопрос таким же образом.