2009-02-18 2 views

ответ

8

Если вы реализуете общий интерфейс IEnumerable<T>, вы почти всегда придется использовать общий метод GetEnumerator - если вы не отбрасывают свой объект явно (необщего) IEnumerable.

Причина заключается в обратной совместимости с .NET 1.0/1.1, которая не поддерживает дженерики.

2

Один общий, другой нет. Я считаю, что компилятор предпочитает использовать общую перегрузку.

4

Обычно GetEnumerator() вызывает GetEnumerator<T>(), поэтому не должно быть большой разницы в поведении. Что касается того, почему существуют два метода, это делается для обратной совместимости и для использования в ситуации, когда T не представляет большой интерес (или просто неизвестен).

9

Причины есть два метода, потому что 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(); 
    } 
} 
+0

+1 - EIMI = Явная реализация элемента интерфейса –

+0

Но как на земле 'Foo: IEnumerable ' имеет смысл? – nawfal

30

Вы обычно реализовать оба. Одна из них - это новая, универсальная версия, которая возвращает типбезопасный перечислитель (IEnumerator<T>). Другой - для совместимости с кодом Legacy (возвращает IEnumerator). Типичная реализация:

public IEnumerator<T> GetEnumerator() { 
    foreach(T item in items) { 
     yield return item; 
    } 
} 

IEnumerator IEnumerable.GetEnumerator() { 
    return GetEnumerator(); 
} 
+0

это помогло мне, избегая лишнего класса для вложенного перечислителя! –

+0

+1. Я также искал поисковые запросы, чтобы найти ссылочную реализацию, которая позволяет избежать вложенного класса перечислителя, и это был первый ответ, к которому я пришел. –

Смежные вопросы