表达式树 - 在循环期间调用 lambda 会导致变量泄漏

问题描述 投票:0回答:1

我发现表达式树没有什么问题,想知道这是一个错误还是一个功能。我有这个代码。第一个函数将 1 赋给变量并返回它。

static class Functions 
{
    static public Expression<Func<int>> GetOne()
    {
        //Returns something like this () = {int x; return x +1;}
        var variable = Expression.Variable(typeof(int));
        var f = Expression.Lambda<Func<int>>(
                            Expression.Block(
                            new[] { variable },
                            Expression.Assign(variable, Expression.Add(variable, Expression.Constant(1)))
        ));
        return f;
    }
    
    static public Expression<Func<int>> ApplyTenTimes()
    {
        var i = Expression.Variable(typeof(int));
        var breakLabel = Expression.Label();
        var f = GetOneB();
        var loop = Expression.Lambda<Func<int>>(
        Expression.Block(
            new[] { i },
            Expression.Block(
            new Expression[] {
            Expression.Loop(Expression.Block(
                        Expression.IfThen(Expression.Equal(i, Expression.Constant(10)),          Expression.Break(breakLabel)),
                Expression.PostIncrementAssign(i),
                Expression.Call(typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }),   Expression.Call( Expression.Invoke(f),typeof(int).GetMethod("ToString", new Type[0]))
                    ))),
            Expression.Label(breakLabel),
            Expression.Invoke(f)
            })));
    
        return loop;
    }
}
f = Functions.GetOneB().Compile();
IEnumerable<int> a = Enumerable.Range(0, 9).Select(_ => f()).ToList();
//Prints 1
Console.WriteLine(f());

f = Functions.ApplyTenTimesB().Compile();
//Prints 1, ..., 10, 1
Console.WriteLine(f());

我预计 f 总是打印 1,因为 0 是 int 的默认值。

c# expression-trees
1个回答
0
投票

Expression.Lambda
的返回值是其主体的返回值。

Expression.Block
的返回值是其最后一个成员的返回值。

您所在区块的最后一个成员是

Expression.Invoke(f)
f
是返回 1 的 lambda。

为什么您对您的

ApplyTenTimesB
返回 1 感到惊讶?

© www.soinside.com 2019 - 2024. All rights reserved.