How|Where закрываются - по сохраненным переменным?

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

8
задан Henk Holterman 17 November 2009 в 09:53
поделиться

2 ответа

Обычно для переменной v2 выделяется некоторое пространство в стеке в начале блока кода, в котором она находится. В конце блока кода (т. Е. В конце итерации) стек заводится обратно (я описываю логический сценарий, а не оптимизированное фактическое поведение). Следовательно, каждый v2 фактически отличается v2 от предыдущей итерации, хотя верно, что в конечном итоге он будет занимать ту же самую ячейку памяти.

Однако компилятор замечает, что v2 используется анонимной функцией, созданной лямбдой. Компилятор поднимает переменную v2 . Компилятор создает новый класс, у которого есть поле Int32 для хранения значения v2 , ему не выделяется место в стеке. Это также делает анонимную функцию методом этого нового типа. (Для простоты я дам этому безымянному классу имя, назовем его «Вещь».)

Теперь в каждой итерации создается новый экземпляр «Вещи». создается, и когда v2 присваивается поле Int32, которое фактически назначается не только точке в стековой памяти. Выражение анонимной функции (лямбда) теперь будет возвращать делегат, который имеет ненулевую ссылку на объект экземпляра, эта ссылка будет на текущий экземпляр «Вещи».

Когда вызывается делегат для анонимной функции, он будет выполняться как метод экземпляра экземпляра "Thing". Следовательно, v2 доступен как поле-член и будет иметь значение, присвоенное ему во время итерации этого экземпляра «Thing»

6
ответ дан 5 December 2019 в 17:38
поделиться

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

(Обратите внимание, что это только для демонстрации принципа, реальный код, сгенерированный компилятором, будет выглядеть не совсем так. Если вы хотите увидеть реальный код, вы можете взглянуть на него с помощью Reflector.)

// first loop
var captures = new Captures();
foreach (var v in values)
{
    captures.Value = v;
    funcs.Add(captures.Function);
}

// second loop
foreach (var v in values)
{
    var captures = new Captures();
    captures.Value = v;
    funcs.Add(captures.Function);
}

// ...

private class Captures
{
    public int Value;

    public int Function()
    {
        return Value;
    }
}
4
ответ дан 5 December 2019 в 17:38
поделиться
Другие вопросы по тегам:

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