访问Func委托C#中的闭包变量

时间:2019-02-28 16:25:59

标签: c# .net .net-4.0 closures

public Func<string, string> getdel()
{
    int i = 1;
    int j = 1;
    return s => s.ToUpper() + (i++);
}

public Func<string, string> aa = getdel()
aa("Test");

关闭变量的值是在委托的Target属性中返回的。我该如何访问关闭变量的值?

((appropriatecast)(aa.Target)).i

当在委托处达到断点时,我可以看到i的值,但是在代码中,此appropriatecast是一个<> c__DisplayClass2_0,它是编译器生成的(已通过IL Disassembler验证)。

1 个答案:

答案 0 :(得分:1)

您不能简单地将闭包转换为它的具体类型,因为该名称是事先未知的,并且(故意)是在C#中无效的名称。

您可以尝试使用dynamic访问其字段:

dynamic target = aa.Target;
int value = target.i;

或带有反射:

var closureType = aa.Target.GetType();
var field = closureType.GetField("i");
var value = (int)field.GetValue(aa.Target);

但是,我强烈建议不要依赖于此,因为不能保证编译器决定生成闭包和命名变量的方式。不同的编译器版本或对lambda似乎不相关的修改可能会产生截然不同的结果,从而导致该代码中断。

如果您可以控制生成委托的代码,建议您使用可公开访问的字段/属性定义自己的类,而不要使用lambda并尝试弄乱编译器生成的闭包。

public class Foo
{
    public int i;    
    public string Bar(string s) => s.ToUpper() + (i++);
}
var foo = new Foo();
Func<string, string> aa = foo.Bar;