gpt4 book ai didi

c# - c# 表达式中的闭包变量捕获问题

转载 作者:可可西里 更新时间:2023-11-01 09:02:08 25 4
gpt4 key购买 nike

我有一个使用表达式树创建委托(delegate)的函数。在此表达式中,我使用从传递给函数的多个参数捕获的变量。实际的表达式树相当大,举个例子:

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();
}

然后我从另一个方法调用这个方法,然后将该函数传递给另一个函数使用。完成所有这些后,我想访问在表达式树中更新的 parent 的内容。

一切似乎都可以编译,我的表达式看起来没问题,但是当我运行它时,我似乎(虽然我不能真正确定)在访问父变量(在表达式/闭包内)时出现空引用异常。

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

谢谢,标记

最佳答案

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) 让编译器为你做这件事,方法是让 it 重写 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 通常成为常量表达式。

但是如果你说

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

编译器不知道您正在做一些需要提升 x 的事情; x 不在 lambda 表达式中。如果您正在使用工厂,编译器会假设您知道自己在做什么,并且不会乱改重写它。您必须自己将其吊起。

关于c# - c# 表达式中的闭包变量捕获问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14585184/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com