рабочий шаблон возврата урожая

Наиболее важное соображение разделяет логику от представления - меньше связи будет делать будущие изменения в обоих намного более простыми.

Вы могли бы даже хотеть рассмотреть использование своего рода системы шаблонной обработки как присяжный острослов .

12
задан Hamish Smith 20 October 2009 в 20:14
поделиться

4 ответа

Nope - far from it; I'll write a long-hand version for you... it is too grungy!


Note it also helps if you understand that the foreach is actually:

using(var iterator = YieldDemo.SupplyIntegers().GetEnumerator()) {
    int i;
    while(iterator.MoveNext()) {
        i = iterator.Current;
         Console.WriteLine("{0} is consumed by foreach iteration", i);
    }
}

using System;
using System.Collections;
using System.Collections.Generic;
static class Program
{
    static void Main()
    {

        foreach (int i in YieldDemo.SupplyIntegers())
        {
            Console.WriteLine("{0} is consumed by foreach iteration", i);
        }
    }
}

 class YieldDemo
  {

    public static IEnumerable<int> SupplyIntegers()
     {
         return new YieldEnumerable();
       }
    class YieldEnumerable : IEnumerable<int>
    {
        public IEnumerator<int> GetEnumerator()
        {
            return new YieldIterator();
        }
        IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
    }
    class YieldIterator : IEnumerator<int>
    {
        private int state = 0;
        private int value;
        public int Current { get { return value; } }
        object IEnumerator.Current { get { return Current; } }
        void IEnumerator.Reset() { throw new NotSupportedException(); }
        void IDisposable.Dispose() { }
        public bool MoveNext()
        {
            switch (state)
            {
                case 0: value = 1; state = 1;  return true;
                case 1: value = 2; state = 2;  return true;
                case 2: value = 3; state = 3; return true;
                default: return false;
            }
        }
    }
}

As you can see, it builds a state machine in the iterator, with the state machine progressed by MoveNext. I've used the pattern with a state field, as you can see how this would work for more complex iterators.

Importantly:

  • any variables in your iterator block become fields on the state machine
  • if you have a finally block (including using), it goes in the Dispose()
  • portions of code leading to a yield return become a case (roughly)
  • yield break becomes a state = -1; return false; (or similar)

The way the C# compiler does this is very complicated, but it makes writing iterators a breeze.

33
ответ дан 2 December 2019 в 03:49
поделиться

короче (пока вы ждете длинную версию от Марка), когда компилятор видит операторы yield, за кулисами он создает для вас новый экземпляр настраиваемого класса, который реализует интерфейс, называемый IEnumerator , который имеет методы Current () и MoveNext () , и отслеживает, где вы в данный момент находитесь в процессе итерации ... В случае выше в качестве вашего примера, он также будет отслеживать значения в списке для перечисления.

1
ответ дан 2 December 2019 в 03:49
поделиться

Это просто синтаксический сахар, .net генерирует для вас класс IEnumerator и реализует методы MoveNext, Current и Reset, а затем генерирует класс IEnumarable GetEnumerator, из которого возвращается этот IEnumerator, вы можете увидеть эти волшебные классы с помощью .net отражатель или ildasm.

Также см. здесь

3
ответ дан 2 December 2019 в 03:49
поделиться

Проще говоря, блоки итераторов (или методы с операторами yield , если можно) преобразуются компилятором в класс, созданный компилятором. Этот класс реализует IEnumerator , а оператор yield преобразуется в «состояние» для этого класса.

Например, это:

yield return 1;
yield return 2;
yield return 3;

может быть преобразовано во что-то похожее на:

switch (state)
{
    case 0: goto LABEL_A;
    case 1: goto LABEL_B;
    case 2: goto LABEL_C;
}
LABEL_A:
    return 1;
LABEL_B:
    return 2;
LABEL_C:
    return 3;

Блоки итераторов можно рассматривать как абстрактные машины состояний. Этот код будет вызываться методами IEnumerator .

2
ответ дан 2 December 2019 в 03:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: