c#事件:如何访问变量

c#事件:如何访问变量,c#,events,scope,C#,Events,Scope,假设 public class Program { public static void Main(string[] args) { Program p = new Program(); A a = new A(); p.Do(a); System.Threading.Thread.Sleep(1000); a.Fire(); } public void Do(A a) {

假设

public class Program
{
    public static void Main(string[] args)
    {
        Program p = new Program();
        A a = new A();
        p.Do(a);
        System.Threading.Thread.Sleep(1000);
        a.Fire();
    }

    public void Do(A a)
    {
        int i = 5;
        a.ChangeViewEvent += () =>
        {
            Console.WriteLine(i);
        };
    }
}

public class A
{
    public delegate void ChangeView();
    public event ChangeView ChangeViewEvent;

    public void Fire()
    {
        if(ChangeViewEvent != null)
            ChangeViewEvent();
    }
}
为什么当触发
ChangeViewEvent
时,事件处理程序仍然能够访问变量
i
?我是说它不应该超出范围吗

为什么在触发ChangeViewEvent时,事件处理程序仍然能够访问变量i?我是说它不应该超出范围吗

不,它是由lambda表达式捕获的。它被“提升”到编译器生成的类中,以便lambda表达式仍然可以访问它,即使它“超出范围”。(请记住,“超出范围”仅表示“无法通过其简单名称访问”。这并不意味着与该变量相关联的存储空间消失,任何其他人都无法访问。)

顺便说一句,这是为什么“值类型存在于堆栈上”这个经常被重复的错误是错误的原因之一。在本例中,您有一个值类型,它实际上被提升到编译器生成的类中,并最终存在于堆中


有关此主题的更多信息,请参阅。

它被称为捕获变量


这的确是个很好的问题!:)