使用Lambda捕获参数

时间:2014-06-02 19:46:26

标签: c# lambda

当我尝试捕获函数的参数时,C#编译器生成了什么代码?

partial class NewClass : Window
{
    public NewClass()
    {
        InitializeComponent();
        new Thread(Work).Start();
    }

    void Work()
    {
        Thread.Sleep(5000); // Simulate time-consuming task
        UpdateMessage("The answer");
    }

    void UpdateMessage(string message)
    {
        Action action = () => txtMessage.Text = message;
        Dispatcher.BeginInvoke(action);
    }
}

我知道lambdas可以在创建新类之后在其词法范围中保存变量 - 其中所述变量存储为字段。这些字段会替换所捕获的任何原始事件。但在这种情况下,由于没有替换原始值,是否会从头开始创建值?这背后的魔力是什么?

2 个答案:

答案 0 :(得分:4)

所以,这里发生的是你在技术上并没有实际关闭txtMessage。你正在做的是关闭this

每个实例方法都有一个类本身类型的隐式第一个参数,称为this。任何实例成员的访问都假定他们正在访问该隐式定义的this变量的成员。

一旦你将所有隐式代码都显式化,它就变成了对任何其他本地范围变量的另一个闭包。

首先我们明确this :(这不是技术上有效的C#,它仅用于演示目的,旨在表示C#编译器对代码的语义表示。 )

void UpdateMessage(NewClass this, string message)
{
    Action action = () => this.txtMessage.Text = message;
    Dispatcher.BeginInvoke(action);
}

然后我们对其进行传统的闭包变换:

class ClosureClass1
{
    public string message;
    public NewClass @this;
    public void AnonymousMethod1()
    {
        @this.txtMessage.Text = message;
    }
}

void UpdateMessage(NewClass this, string message)
{
    ClosureClass1 closure = new ClosureClass1();
    closure.@this = this;
    closure.message = message;
    Action action = closure.AnonymousMethod1;
    Dispatcher.BeginInvoke(action);
}

答案 1 :(得分:2)

NewClass包含一个类型为<> c__DisplayClass1类的私有字段,其中包含一个公共字符串字段' message'。每次调用UpdateMessage时,该方法都会实例化<> c__DisplayClass1类的新实例,并将传递给UpdateMessage方法的消息(按值)分配。它还包含< UpdateMessage> b__0这是要执行的操作(使用消息值分配文本框)。文本框值使用'此'设置。字段是MainWindow类。

enter image description here

enter image description here

enter image description here

希望这能回答你的问题!