加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-15 04:05:18 所属栏目:百科 来源:网络整理
导读:我有一个使用表达式树创建一个委托的函数.在这个表达式中,我使用从传入函数的多个参数捕获的变量.实际的表达式树是相当大的例子: Delegate GenerateFunctionT(T current,IListT parents) { var currentExpr = Expression.Parameter(typeof(T),"current"); v
我有一个使用表达式树创建一个委托的函数.在这个表达式中,我使用从传入函数的多个参数捕获的变量.实际的表达式树是相当大的例子:
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表达式内.如果您正在使用工厂,编译器会假设您知道您正在做什么,并且不会改变它.你必须自己提升.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读