Алгоритм для реализации C# приводит к оператору

31
задан cynicalman 26 September 2008 в 16:38
поделиться

3 ответа

Конкретный пример кода, на который Вы смотрите, включает ряд преобразований. Обратите внимание на то, что это - приблизительное описание алгоритма. Подлинные имена, используемые компилятором и точным кодом, который это генерирует, могут отличаться. Идея является тем же, как бы то ни было.

первое преобразование является "foreach" преобразованием, которое преобразовывает этот код:

foreach (var x in y)
{
   //body
}

в этот код:

var enumerator = y.GetEnumerator();
while (enumerator.MoveNext())
{
    var x = enumerator.Current;
    //body
}

if (y != null)
{
    enumerator.Dispose();
}

второе преобразование находит все операторы возврата урожая в теле функции, присваивает номер каждому (значение состояния) и создает "goto, маркируют" right after the yield.

The third transformation lifts all the local variables and function arguments in the method body into an object called a closure.

Given the code in your example, that would look similar to this:

 class ClosureEnumerable : IEnumerable<string>
 {
    private IEnumerable<string> args;
    private ClassType originalThis;
    public ClosureEnumerator(ClassType origThis, IEnumerable<string> args)
    {
        this.args = args;
        this.origianlThis = origThis;
    }
    public IEnumerator<string> GetEnumerator()
    {
        return new Closure(origThis, args);
    }
 }

class Closure : IEnumerator<string>
{
    public Closure(ClassType originalThis, IEnumerable<string> args)
    {
        state = 0;
        this.args = args;
        this.originalThis = originalThis;
    }

    private IEnumerable<string> args;
    private IEnumerator<string> enumerator2;
    private IEnumerator<string> argEnumerator;

    //- Here ClassType is the type of the object that contained the method
    //  This may be optimized away if the method does not access any 
    //  class members
    private ClassType originalThis;

    //This holds the state value.
    private int state;
    //The current value to return
    private string currentValue;

    public string Current
    {
        get 
        {
            return currentValue;
        }
    }
}

The method body is then moved from the original method to a method inside "Closure" called MoveNext, which returns a bool, and implements IEnumerable. MoveNext. Any access to any locals is routed through "this", and any access to any class members are routed through this.originalThis.

Any "expr возврата урожая", переводится в:

currentValue = expr;
state = //the state number of the yield statement;
return true;

Любой оператор завершения урожая переводится в:

state = -1;
return false;

существует "неявный" оператор завершения урожая в конце функции. Оператор переключения затем представлен в начале процедуры, которая смотрит на число состояния и переходы к связанной маркировке.

исходный метод затем переводится во что-то вроде этого:

IEnumerator<string> strings(IEnumerable<string> args)
{
   return new ClosureEnumerable(this,args);
}

то, что состояние метода все продвинуто в объект и что метод MoveNext использует оператор переключения / переменная состояния - то, что позволяет итератору вести себя, как будто управление пасуется назад к точке сразу после последнего "оператора" возврата урожая, которым называют следующий раз "MoveNext".

важно указать, однако, что преобразование, используемое компилятором C#, не является лучшим способом сделать это. Это страдает от низкой производительности при попытке использовать "урожай" с рекурсивными алгоритмами. Существует хорошая статья, которая обрисовывает в общих чертах лучший способ сделать это здесь:

http://research.microsoft.com/en-us/projects/specsharp/iterators.pdf

Это стоит чтения, если Вы еще не считали его.

59
ответ дан 27 November 2019 в 21:53
поделиться

Просто определенный этот вопрос - я записал статью о нем недавно. Я должен буду добавить другие ссылки, упомянутые здесь статье хотя...

7
ответ дан 27 November 2019 в 21:53
поделиться

Raymond chen отвечает на это; http://blogs.msdn.com/b/oldnewthing/archive/2008/08/12/8849519.aspx

(отредактированный для указания на часть 1 ряда, не часть 4)

7
ответ дан 27 November 2019 в 21:53
поделиться
Другие вопросы по тегам:

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