微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在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表达式内.如果您正在使用工厂,编译器会假设您知道您正在做什么,并且不会改变它.你必须自己提升.

原文地址:https://www.jb51.cc/csharp/92832.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐