Зачем реализовывать IEnumerable (T), если я могу просто определить ОДИН GetEnumerator?

ОбновитьЯ ценю все комментарии, которые по существу составили единодушную оппозицию. Хотя каждое возражение было обоснованным, я чувствую, что последний гроб в гробу былПроницательное наблюдение Ани что, в конечном счете, дажеодин мизерную выгода, которую якобы предложила эта идея - устранение стандартного кода - была сведена на нет тем фактом, что сама идея потребуетсвоя стандартный код.

Так что да, считай меня убежденным: это была бы плохая идея.

И просто для того, чтобы хоть как-то спасти мое достоинство: я мог бы подыграть ему ради аргумента, но мне никогда не приходило в голову эту идею с самого начала - просто любопытно услышать, что другие говорят об этом. Честный.

Прежде чем отклонить этот вопрос как абсурдный, я прошу вас рассмотреть следующее:

IEnumerable<T>&nbsp;наследуется от *IEnumerable, что означает, что любой тип, который реализуетIEnumerable<T>&nbsp;как правило, должны реализоватьи то и другое IEnumerable<T>.GetEnumerator а также&nbsp;(Явно)IEnumerable.GetEnumerator, Это в основном составляет стандартный код.Вы можетеforeach&nbsp;над любым типом, который имеетGetEnumerator&nbsp;метод, если этот метод возвращает объект некоторого типа сMoveNext&nbsp;метод иCurrent&nbsp;имущество. Так что если ваш тип определяетодин&nbsp;метод с подписьюpublic IEnumerator<T> GetEnumerator()это законно перечислять, используяforeach.Очевидно, что существует много кода, который требуетIEnumerable<T>&nbsp;интерфейс - например, в основном все методы расширения LINQ. К счастью, чтобы перейти от типа, который вы можетеforeach&nbsp;наIEnumerable<T>&nbsp;тривиально с использованием автоматической генерации итератора, который C # поставляет черезyield&nbsp;ключевое слово.

Итак, собрав все это вместе, у меня возникла безумная идея: что если я просто определю свой собственный интерфейс, который выглядит следующим образом:

public interface IForEachable<T>
{
    IEnumerator<T> GetEnumerator();
}

затем&nbsp;всякий раз, когда я определяю тип, который я хочу перечислить, я реализуюэтот&nbsp;интерфейс вместоIEnumerable<T>, устраняя необходимость реализации двухGetEnumerator&nbsp;методы (один явный). Например:

class NaturalNumbers : IForEachable<int>
{
   public IEnumerator<int> GetEnumerator()
   {
       int i = 1;
       while (i < int.MaxValue)
       {
           yield return (i++);
       }
   }

   // Notice how I don't have to define a method like
   // IEnumerator IEnumerable.GetEnumerator().
}

в заключение, чтобы сделать этот тип совместимым с кодом, которыйделает&nbsp;ожидатьIEnumerable<T>&nbsp;интерфейс, я могу просто определить метод расширения, чтобы перейти от любогоIForEachable<T>&nbsp;дляIEnumerable<T>&nbsp;вот так:

public static class ForEachableExtensions
{
    public static IEnumerable<T> AsEnumerable<T>(this IForEachable<T> source)
    {
        foreach (T item in source)
        {
            yield return item;
        }
    }
}

Мне кажется, что это позволяет мне проектировать типы, которые могут использоваться всеми способами в качестве реализацийIEnumerable<T>, но без этого надоедливого явногоIEnumerable.GetEnumerator&nbsp;реализация в каждом.

Например:

var numbers = new NaturalNumbers();

// I can foreach myself...
foreach (int x in numbers)
{
    if (x > 100)
        break;

    if (x % 2 != 0)
        continue;

    Console.WriteLine(x);
}

// Or I can treat this object as an IEnumerable<T> implementation
// if I want to...
var evenNumbers = from x in numbers.AsEnumerable()
                  where x % 2 == 0
                  select x;

foreach (int x in evenNumbers.TakeWhile(i => i <= 100))
{
    Console.WriteLine(x);
}

Что вы, ребята, думаете об этой идее? Я что-то упускаю, почему это будет ошибкой?

Я понимаю, что это, вероятно, кажется слишком сложным решением для того, что не так уж важно для начала (я сомневаюсь никогодействительно&nbsp;заботится так много о необходимости явно определитьIEnumerable&nbsp;интерфейс); но это просто пришло мне в голову, и я не вижу каких-либо очевидных проблем, которые возникнет при таком подходе.

В общем, если я могу написать умеренное количество кодаодин раз&nbsp;чтобы избавить себя от необходимости писать небольшое количество кодамного временидля меня это того стоит.

* Это правильная терминология для использования? Я всегда не решаюсь сказать, что один интерфейс «наследует» от другого, так как кажется, что он не отражает должным образом отношения между ними. Но, возможно, это правильно.