在c#表达式中关闭变量捕获的问题

前端之家收集整理的这篇文章主要介绍了在c#表达式中关闭变量捕获的问题前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个使用表达式树创建一个委托的函数.在这个表达式中,我使用从传入函数的多个参数捕获的变量.实际的表达式树是相当大的例子:
Delegate GenerateFunction<T>(T current,IList<T> parents) {
    var currentExpr = Expression.Parameter(typeof(T),"current");
    var parentsExpr = Expression.Parameter(parents.getType(),"parents");
    var parameters = new List<ParameterExpression>();

    ....

    return Expression.Lambda(Expression.Block(new List<ParameterExpression> { parentsExpr,currentExpr },....),parameters.ToArray()).Compile();
}

然后在将该函数传递给另一个使用的函数之前,从另一种方法调用方法.一旦完成,我想访问在表达式树中更新的父母的内容.

一切似乎编译,我的表达式看起来很好,但是当我运行它时,我出现(虽然我不能确定)在访问父变量(表达式/闭包)内时得到空引用异常.

我想我想知道我是否做错了事情,或者这是否可能以及了解发生了什么的提示.我似乎无法在方法中找到任何提升的(?)局部变量,所以我想知道它们是否被捕获?

谢谢,
标记

解决方法

I don’t seem to be able to find any hoisted local variables within the method so I’m wondering whether they’re being captured at all?

看起来你正在自己构建表达式树lambda,通过“手动”调用工厂方法.编译器不知道这是你在做什么;它只是看到方法调用.如果你想要当地人被提升,那么你将不得不(1)让编译器为你做,通过重写lambda,或者(2)提升你自己.

那是:

int x = 123;
Expression<Func<int>> ex = ()=>x;

编译器会重写lambda并将其提升给您,就像您所说的那样:

Closure c = new Closure();
c.x = 123;
Expression<Func<int>> ex = ()=>c.x;

其中c通常变为Constant表达式.

但如果你说

Expression<Func<int>> ex = Expression.Lambda( ...something that uses x ... );

编译器不知道你在做什么,需要提升x; x不在lambda表达式内.如果您正在使用工厂,编译器会假设您知道您正在做什么,并且不会改变它.你必须自己提升.

猜你在找的C#相关文章