5

认为

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?我的意思是它不应该超出范围吗?

4

2 回答 2

6

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

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

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

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

于 2012-04-05T16:56:52.890 回答