IEnumerable<T> предоставляет два метода GetEnumerator — в чем разница между ними?
-
05-09-2019 - |
Вопрос
Когда я реализую IEnumerable<T>
интерфейс я вижу два GetEnumerator
методы:один возвращается IEnumerator
и другие IEnumerator<T>
.Когда я буду использовать тот или иной?
Решение
Если вы реализуете IEnumerable<T>
универсальный интерфейс, вам почти всегда придется использовать универсальный метод GetEnumerator - если только вы явно не приведете свой объект к (неуниверсальному) IEnumerable.
Причина — обратная совместимость с .NET 1.0/1.1, которая не поддерживала дженерики.
Другие советы
Обычно вы реализуете оба варианта.Одна из них — более новая, универсальная версия, которая возвращает типобезопасный перечислитель (IEnumerator<T>
).Другой предназначен для совместимости с устаревшим кодом (возвращает IEnumerator
).Типичная реализация:
public IEnumerator<T> GetEnumerator() {
foreach(T item in items) {
yield return item;
}
}
IEnumerator IEnumerable.GetEnumerator() {
return GetEnumerator();
}
Причина, по которой существует два метода, заключается в том, что IEnumerable<T>
наследует IEnumerable
интерфейс, поэтому вы видите общий метод из IEnumerable<T>
и необщий метод из IEnumerable
.
Вот как вы хотите реализовать интерфейс в своем типе:
class Foo : IEnumerable<Foo>
{
public IEnumerator<Foo> GetEnumerator()
{
// do your thing here
}
// do a EIMI here and simply call the generic method
IEnumerator IEnumerable.GetEnumerator()
{
this.GetEnumerator();
}
}
Обычно GetEnumerator()
звонки GetEnumerator<T>()
, поэтому большой разницы в поведении быть не должно.Что касается того, почему существует два метода, то это сделано для обратной совместимости и для использования в ситуации, когда T
не представляет большого интереса (или просто неизвестен).
Один универсальный, другой нет.Я считаю, что компилятор предпочитает использовать общую перегрузку.