«Доходность» в IEnumerator или IEnumerable?

Я искал эту точку, и я еще не получил никакой информации об этом!.

Я видел много видео и красную кучу статей о «доходности», и я думаю, что лучше понимаю это, но есть момент, который я не могу понять.

Каков правильный интерфейс, я должен использовать доходность возврата в нем? (Конечно, возврат доходности будет использоваться в цикле, но в каком интерфейсе).

Я имею в виду, что в этом пункте есть различия, я видел, как некоторые люди создавали "итератор" внутри IEnumerator, например:

static string[] Names = { "Name1", "Name2", "Name3" };

    static IEnumerator Test()
    {
        for (int i = 0; i < Names.Length; i++)
        {
            yield return Names[i];
        }
    }

и некоторые другие используют IEnumerable :

        static IEnumerable Test()
    {
        for (int i = 0; i < Names.Length; i++)
        {
            yield return Names[i];
        }
    }

Я предполагаю, что лучше создать «Итератор», используя «Возврат доходности» в интерфейсеIEnumerable, потому что в целом IEnumerable отвечает за доступ к классу (точнее, он возвращает экземпляр класса (объекта)), который защищает Логика итерации. и что именно происходит компилятором (сахар ключевого слова yield) в этом случае.

 private static IEnumerable Test() => new <Test>d__1(-2);
//decompiled code of Test() method above Using reflector tool

Любые идеи по этому поводу?


person Ammar Bamhdi    schedule 24.09.2018    source источник
comment
Вернуть IEnumerable, а не IEnumerator. Все методы расширения linq используют IEnumerable.   -  person FCin    schedule 24.09.2018
comment
Вам нужно определить IEnumerator только тогда, когда вам нужен нестандартный способ перечисления чего-либо. Ваш метод Test должен возвращать IEnumerable, который можно перечислить с помощью цикла foreach.   -  person mm8    schedule 24.09.2018


Ответы (1)


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

IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
    if (state == Created && initialThreadId == Environment.CurrentManagedThreadId)
    {
        state = EnumerationStarted;
        return this;
    }
    else
        return new GeneratedEnumerableEnumerator(state: EnumerationStarted);
}

state в приведенном выше коде является int, Created и EnumerationStarted не являются реальными именами констант. state может иметь много внутренних значений в зависимости от сложности вашей реализации.

Каков правильный интерфейс, если я должен использовать доходность возврата

Это зависит от вашего случая. Если вы реализуете IEnumerable<T>.GetEnumerator() в своем пользовательском типе коллекции, используйте IEnumerator<T>. И если вам нужно вернуть IEnumerable<T>, содержимое которого можно легко получить, используйте IEnumerable<T>. Оба могут иметь смысл.

person György Kőszeg    schedule 24.09.2018