对内联事件处理程序参数的好奇

本文关键字:参数 好奇 程序 事件处理 | 更新日期: 2023-09-27 17:59:38

我想知道一些事情。假设我有一个名为SomethingChanged的事件,有两个参数。第一个是触发事件的发送方。第二个只是一个数字。

案例1:

我在SenderClass:中定义了此事件

public event Action<SenderClass, int> SomethingChanged;

通常情况下,我可以像这样附加事件处理程序:

item.SomethingChanged += (sender, p) =>
{
    if (p == 1) sender.F1();
    else sender.F2();
};

案例2:

但如果我删除发件人参数:

public event Action<int> SomethingChanged;

它不会改变任何东西,我仍然可以使用它:

item.SomethingChanged += p =>
{
    if (p == 1) item.F1();
    else item.F2();
};

很明显,通过删除发件人,以下用法不再可行:

item.SomethingChanged += item_SomethingChanged;
private void item_SomethingChanged(SenderClass sender, int p)
{
    if (p == 1) sender.F1();
    else sender.F2();
}

问题:

但我好奇的是编译器是如何在Case2中找到那个发送方的?它是使用反射,还是两者都转换为相同的程序集代码?或

对内联事件处理程序参数的好奇

这是因为在第二种情况下,您使用的是item局部变量,它可以从lambda中访问。编译器不需要了解sender变量,因为它根本没有被使用,也没有被提供,在第二种情况下根本不存在。

从Lambda表达式中的可变范围:

lambda可以引用在定义lambda的封闭方法或类型的作用域中的外部变量。以这种方式捕获的变量被存储在lambda表达式中以供使用,即使变量会超出范围并被垃圾收集。在lambda表达式中使用外部变量之前,必须对其进行明确赋值。

如果你想了解变量捕获是如何发生的,请查看评论中@Sriram提供的链接中的答案。