You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何用Expression构建的Add方法无法修改ref参数的字段?

问题根源:表达式树的调用方式错误

你的表达式构建逻辑本身是完全正确的——从DebugView可以看到,生成的代码确实会对ref参数的字段执行加法赋值操作。问题出在你调用表达式的方式上:如果你直接使用表达式树的Invoke方法来执行,它无法正确处理值类型的ref参数,导致原始变量不会被修改。

为什么会这样?因为表达式树的Invoke方法在处理值类型的ref参数时,会创建一个临时副本传递给表达式执行,执行完成后并不会把副本的修改同步回原始变量。而我们需要的是直接操作原始变量的内存地址,这必须通过编译后的委托实例来实现。

解决方案:编译表达式树为委托

你需要先调用表达式树的Compile()方法,生成对应的Add<T>委托实例,再通过这个委托来调用,这样才能正确修改ref参数指向的原始变量。

修正后的测试代码示例:

// 定义你的结构体
public struct MyStruct { public int Field1; }

// 构建表达式树
var addExpression = BuildExpression<MyStruct>();
// 编译成委托实例
var addDelegate = addExpression.Compile();

// 测试变量
MyStruct x = new MyStruct { Field1 = 1 };
MyStruct y = new MyStruct { Field1 = 2 };

// 通过委托调用,此时原始变量x会被正确修改
addDelegate(ref x, y);

Console.WriteLine(x.Field1); // 输出3,符合预期

额外验证

你的表达式构建代码没有问题:Expression.Block正确组合了所有字段的加法赋值操作,Expression.AddAssign也正确针对ref参数的字段进行左值操作。只要通过编译后的委托调用,就能得到你想要的结果。

内容的提问来源于stack exchange,提问作者Aleks Andreev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 06:46:48