我有以下代码:
string prefix = "OLD:"; FuncprependAction = (x => prefix + x); prefix = "NEW:"; Console.WriteLine(prependAction("brownie"));
因为编译器用一个闭包替换了前缀变量"NEW:brownie"被打印到控制台.
是否有一种简单的方法可以阻止编译器在仍然使用lambda表达式的同时解除前缀变量?我想要一种使我的Func工作方式相同的方法:
FuncprependAction = (x => "OLD:" + x);
我需要这个的原因是我想序列化结果委托.如果前缀变量在非序列化类中,则上述函数不会序列化.
我现在可以看到的唯一方法是创建一个新的可序列化类,它将字符串存储为成员变量并具有字符串prepend方法:
string prefix = "NEW:"; var prepender = new Prepender {Prefix = prefix}; FuncprependAction = prepender.Prepend; prefix = "OLD:"; Console.WriteLine(prependAction("brownie"));
有助手类:
[Serializable] public class Prepender { public string Prefix { get; set; } public string Prepend(string str) { return Prefix + str; } }
这似乎是让编译器变得"愚蠢"的额外工作.
我现在看到了潜在的问题.它比我想象的要深.基本上,解决方案是在序列化之前修改表达式树,方法是将所有不依赖于参数的子树替换为常量节点.这显然被称为"funcletization".有它的解释这里.