Почему List объявляет GetEnumerator() и IEnumerable.GetEnumerator()?

#c# #interface #ienumerable #ienumerator #explicit-interface

Вопрос:

Почему Список определяет эти три метода?

     public Enumerator GetEnumerator()
        => new Enumerator(this);

    IEnumerator<T> IEnumerable<T>.GetEnumerator()
        => new Enumerator(this);

    IEnumerator IEnumerable.GetEnumerator()
        => new Enumerator(this);
 

Все они делают одно и то же. Разве не было бы достаточно просто иметь это:

 public Enumerator GetEnumerator()
        => new Enumerator(this);
 

Комментарии:

1. docs.microsoft.com/en-us/dotnet/csharp/programming-guide/…

2. Enumerator GetEnumerator() позволяет ему возвращать перечислитель структуры для использования в foreach циклах без выделения. IEnumerator<T> IEnumerable<T>.GetEnumerator() позволяет реализовать IEnumerator<T> GetEnumerator() метод из IEnumerable<T> интерфейса, чтобы вы могли сделать IEnumerable<T> x = new List<T>(); foreach (var item in x) ...

Ответ №1:

Разве не было бы достаточно просто иметь это:

 public Enumerator GetEnumerator()
       => new Enumerator(this);
 

Нет, это не так, потому что это не будет реализовывать ни IEnumerable<T> то , ни IEnumerable другое, где GetEnumerator() методы имеют возвращаемые типы IEnumerator<T> и IEnumerator соответственно.

Типы возвращаемых данных должны совпадать для реализации интерфейса.

Действительно, это легко проверить на себе:

 using System.Collections;
using System.Collections.Generic;

public class MyList<T> : IEnumerable<T>
{
    public Enumerator GetEnumerator() =>
        new Enumerator();

    // Implement this fully so we can concentrate on IEnumerable<T>
    public struct Enumerator : IEnumerator<T>
    {
        public T Current => defau<
        object IEnumerator.Current => defau<
        public bool MoveNext() => true;
        public void Reset() {}
        public void Dispose() {}
    }
}
 

Это приводит к ошибкам:

  • ошибка CS0738: «myList<T>» не реализует элемент интерфейса » IEnumerable<T><T>.GetEnumerator ()». «myList<T><T>.GetEnumerator ()» не может реализовать » IEnumerable<T><T>.GetEnumerator ()», потому что у него нет соответствующего возвращаемого типа » IEnumerator<T><T>».
  • ошибка CS0738: «myList<T>» не реализует элемент интерфейса » IEnumerable.GetEnumerator()’. ‘myList<T>.GetEnumerator()’ не может реализовать ‘IEnumerable.GetEnumerator ()», потому что у него нет соответствующего возвращаемого типа «IEnumerator».