IEnumerable <int>Требуется также неуниверсальный IEnumerator? - PullRequest
11 голосов
/ 27 ноября 2011

3 вопроса:

1) почему выходное значение берется из обобщенной функции NON ?

2) почему у меня есть для реализации ТАКЖЕ НЕ универсальной функции?

3) Что мне нужно сделать, если я хочу увидеть вывод универсальной функции (целые числа)?

enter image description here

Ответы [ 3 ]

8 голосов
/ 27 ноября 2011
  1. Ключевое слово foreach не требует, чтобы коллекция вообще реализовывала IEnumerable;скорее он будет вызывать любые определенные GetEnumerator методы.

  2. IEnumerable<T> реализует IEnumerable по соображениям совместимости.

  3. Вы должны реализоватьIEnumerable.GetEnumerator() явно и имеет нормальный метод возврата IEnumerator<T>.

Если в классе есть нормальный метод GetEnumerator() (в отличие от явной реализации интерфейса), компилятор вызоветit.
Спецификация гласит:

  • В противном случае определите, есть ли у типа X соответствующий метод GetEnumerator:
    • Выполните поиск члена для типа X с идентификатором GetEnumeratorи нет аргументов типа.Если поиск члена не приводит к совпадению, или он производит неоднозначность, или производит совпадение, которое не является группой методов, проверьте перечислимый интерфейс, как описано ниже.Рекомендуется, чтобы было выдано предупреждение, если при поиске члена генерируется что-либо, кроме группы методов или без совпадения.
    • Выполните разрешение перегрузки, используя результирующую группу методов и пустой список аргументов.Если разрешение перегрузки не приводит к применимым методам, приводит к неоднозначности или приводит к единственному лучшему методу, но этот метод является либо статическим, либо не общедоступным, проверьте перечислимый интерфейс, как описано ниже.Рекомендуется выдавать предупреждение, если разрешение перегрузки создает что-либо, кроме однозначного метода общего экземпляра или неприменимых методов.
    • [...]
  • В противном случае проверьтедля перечислимого интерфейса:
6 голосов
/ 27 ноября 2011

1) Вывод берется из неуниверсальной функции, поскольку она определена неявно (а универсальная функция определена явно).

2) IEnumerable<T> наследуется от IEnumerable, поэтому любой тип, наследуемый от IEnumerable<T>, также должен реализовывать члены IEnumerable

3) Сделайте общее определение неявным, а неуниверсальное определение явным, например,

public class Class1 : IEnumerable<int>
{
    public IEnumerator<int> GetEnumerator()
    {
        yield return 1;
        yield return 2;
        yield return 3;
        yield return 4;
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}

Обратите внимание, что универсальный перечислитель можно вернуть из неуниверсального метода, поскольку IEnumerator<T> наследуется от IEnumerator.

3 голосов
/ 27 ноября 2011

Вам необходимо реализовать оба, так как IEnumerable<T> является производным от IEnumerable. Чтобы вызвать явно реализованный метод, вам нужно привести его к этому интерфейсу.

Но обычно вы реализуете не универсальный метод явно, а универсальный метод неявно. Таким образом foreach будет использовать универсальный метод. foreach использует метод GetEnumerator() для типа коллекции и использует методы интерфейса, только если этот метод отсутствует.

Типичная реализация:

public IEnumerator<int> GetEnumerator()
{
   ...
}

System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
  return GetEnumerator();//Forward to strongly typed version
}
...