Ну, сборщик мусора не собирает его сразу . Это не может, очевидно.
Внутренне, когда вы делаете что-то вроде foreach над своим методом, он вызывает GetEnumerator (), а затем MoveNext () много раз для получения каждой вещи. Перечислители являются одноразовыми, и когда перечислитель удаляется - foreach располагает его для вас в конце цикла - сборщик мусора может свободно очищать любые объекты, находящиеся в вашем итераторе.
Итак, если у вас много дорогостоящих состояний в итераторе, и вы долго его повторяете, то вы, вероятно, захотите либо не использовать yield return, либо сразу оценить все перечисление, вызвав что-то вроде ToArray (), а затем смотреть на это.
РЕДАКТИРОВАТЬ : Итак, в ответ на ваш последний вопрос - как вы можете убедиться, что он утилизируется - вам не нужно делать ничего особенного, если вы используете для этого LINQ или конструкции foreach потому что они сами позаботятся об этом с помощью своей обычной магии. Если вы вручную получаете перечислитель, убедитесь, что вы вызвали Dispose () для него, когда закончите, или поместите его в блок using.