Комментарии 3
Компилятор превращает foreach в try/finally с вызовом Dispose у перечислителя
Вот ведь, так-то оно на подсознательном уровне ясно, но чтобы вот так конкретно - никогда даже не задумывался :)
...у нас, правда, стандартные енумераторы используются разве что в LINQ-выражениях, а это точно не горячий путь - так что почти простительно ;)
Зато теперь легко могу объяснить, почему (без крайней необходимости) нельзя имплементировать IEnumerator<T> ;)
И как обычно - отличная статья, спасибо.
...не в тему, но как-бы кстати: недавно с удивлением обнаружил, что MemoryExtensions.Sort<T, TComparer>(this Span<T> span, TComparer comparer) where TComparer : IComparer<T>? - а попросту span.Sort(MyCustomComparer.StaticReadOnlySingletonInstance) - на каждый вызов аллоцирует инстанс делегата MyCustomComparer.Compare (для стандартного Comparer<T>.Default - не аллоцирует, и на том спасибо).
Выход - самому кешировать делегат и вызывать span.Sort(comparisonDelegate).
Не знаю кто как - а я от высокоэффективного аллок-фри АПИ такого не ожидал.
Я это к чему - может пригодится как идея для очередных бенчмарков, найдёте ещё каких засад, поделитесь ;)
Спасибо! Идея пригодилась и вот результат https://habr.com/ru/articles/1073128/

Бенчмаркая try/finally: один finally — и метод в 6,45 раза медленнее