С#:IEnumerator<T> в инструкции использования
-
06-09-2019 - |
Вопрос
Мне было любопытно посмотреть, как SingleOrFallback
метод был реализован в ПодробнееLinq и обнаружил то, чего раньше не видел:
public static T SingleOrFallback<T>(this IEnumerable<T> source, Func<T> fallback)
{
source.ThrowIfNull("source");
fallback.ThrowIfNull("fallback");
using (IEnumerator<T> iterator = source.GetEnumerator())
{
if (!iterator.MoveNext())
{
return fallback();
}
T first = iterator.Current;
if (iterator.MoveNext())
{
throw new InvalidOperationException();
}
return first;
}
}
Почему IEnumerator<T>
в using
заявление?Стоит ли об этом думать при использовании foreach
на IEnumerable<T>
также?
Побочный вопрос: Что конкретно делает этот метод?Возвращает ли он резервный элемент всякий раз, когда исходная последовательность не содержит ровно одного элемента?
Решение
IEnumerator<T>
простирается IDisposable
, так что вы должен используйте это в операторе использования. foreach
делает это автоматически.(Необщий IEnumerator
не делает продлевать IDisposable
но компилятор C# по-прежнему генерирует код для вызова Dispose
условно.Это было одно из (немногих) изменений между C# 1.0 и 1.2, где 1.2 по какой-то причине — это версия, поставляемая с .NET 1.1.)
Вот статья объясняя, почему это важно в контексте блоков итераторов.
Что касается того, что делает метод:
- Если последовательность пуста, верните резервный элемент.
- Если в последовательности ровно один элемент, верните его.
- Если последовательность содержит более одного элемента, выдайте исключение
ПС:Приятно видеть, что MoreLinq привлекает внимание :)
Другие советы
Некоторые перечислители будут вести себя плохо, если Dispose не вызываться;это так же верно как для неуниверсальных, так и для универсальных (неуниверсальные требуют, чтобы код либо вводил вызов Dispose, либо приводил его к IDisposable, а затем вызывал IDisposable.Dispose).По привычке рекомендуется обеспечить удаление объектов IEnumerator;Я бы посчитал это необходимым для корректности любой процедуры, которая принимает IEnumerable неизвестного типа.