当我尝试捕获函数的参数时,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可以在创建新类之后在其词法范围中保存变量 - 其中所述变量存储为字段。这些字段会替换所捕获的任何原始事件。但在这种情况下,由于没有替换原始值,是否会从头开始创建值?这背后的魔力是什么?
答案 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类。
希望这能回答你的问题!