IEnumerable, IEnumerator, yield

87
10 февраля 2021, 08:10

Форумчане, привет !

Продолжаю разбираться с синтаксисом C#. В очередной раз пересмотрел все источники и понимание так и не пришло. Разобрался как работают IEnumerable и IEnumerator: для коллекции необходимо создать некий объект - итератор, который будет осуществлять перебор элементов коллекции. Для этого мы реализуем IEnumerable, который содержит в себе 1 метод- GetEnumerator(). Возвращаемое значение метода типа IEnumerator и явно вызываем GetEnumerator из IEnumerable. IEnumerator содержит в себе 3 метода: двигает индекс, возвращает объект и возвращает указатель на начало коллекции. Понял как работает foreach. НО ! Как и где их наследовать нет понимания. А yield вообще не понимаю что за зверь и с чем его едят. Вопросы:

1.Какие классы должны реализовывать IEnumerable и IEnumerator ? Те, которые содержат коллекцию или те, в которых мы будем её перебирать ??

  1. В каком месте их реализовывать ? Неужели надо прописывать реализацию всех методов IEnumeratorа ?

  2. Почему foreach работает в методе Main без реализации IEnumerable и IEnumerator ?

    namespace ConsoleApp2
    {
        class Person
        {
            public string Name { get; set; }
            public string LastName { get; set; }
            public int Age { get; set; }
        public Person(int age)
        {
            Age = age;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            List<Person> newCollection = new List<Person>();
            for(int i = 0; i < 5; i++)
            {
                newCollection.Add(new Person(i));
            }
            foreach(Person person in newCollection)
            {
                Console.WriteLine(person.Age);
            }
            Console.ReadKey();
        }
    }
    
  3. Что такое yield и в каких случаях нам следует его применять ?

Буду благодарен за ответы. В идеале, максимально простым языком на котиках и собачках.

Answer 1

1.Какие классы должны реализовывать IEnumerable и IEnumerator ? Те, которые содержат коллекцию или те, в которых мы будем её перебирать ??

Все, что вы планируете перебирать

В каком месте их реализовывать ? Неужели надо прописывать реализацию всех методов IEnumeratorа ?

Чтобы реализовать интерфейс, надо отнаследоваться и прописать все методы интерфейса

Почему foreach работает в методе Main без реализации IEnumerable и IEnumerator ?

Это называется утиная типизация. Foreach может перечислить всё, что имеет метод GetEnumerator. Но в вашем примере тут

    foreach(Person person in newCollection)
    {
        Console.WriteLine(person.Age);
    }

Вы перебираете List<Person>, который реализует IEnumerable

Что такое yield и в каких случаях нам следует его применять ?

yield вы можете использовать, если ваша последовательность бесконечна или вы не хотите создавать коллекцию в качестве результата. Например вот эта функция возвращает бесконечную последовательность Фибоначчи

public IEnumerable<int> GetFibonacci()
{
    yield return 1;
    yield return 1;
    var x=1;
    var y=1;        
    while (true) {
        var tmp = x+y;
        x = y;
        y = tmp;
        yield return tmp;
    }
}

Но, так как последовательность вычисляется лениво, то, например, можно взять только первые 10 чисел, которые посчитаются, а остальные не считать.

foreach (var rand in GetFibonacci().Take(10))
    Console.WriteLine(rand);

На выходе будет

1
1
2
3
5
8
13
21
34
55
READ ALSO
Json deserealization to anonimous object Web-Api 2 C#

Json deserealization to anonimous object Web-Api 2 C#

Имеется сервер Web-Api 2, который обращается к БД через dapperНа сервере имеется метод для вызова процедуры из БД, подобный этому:

99
Поиск ID выбранных элементов

Поиск ID выбранных элементов

Есть combobox с мультивыбором (источник)В него из БД приходят items

111
Какой смысл создавать индекс для этого столбца?

Какой смысл создавать индекс для этого столбца?

Занимаюсь по учебнику, в нем рассказывается про создание таблиц и индексовЕсть таблица classics, содержащая имена авторов, названия книг, жанр...

102
Как перевести 4 байта DWORD в читаемую строку

Как перевести 4 байта DWORD в читаемую строку

У меня имеется файл, в начале которого содержится 4 байта DWORD с некоторым id и я без понятия как его сделать читабельным

97