首页 新闻 赞助 找找看

闭包延长了委托的作用域?

1
悬赏园豆:10 [待解决问题]

上代码

         internal class Program
    {
        static void Main(string[] args)
        {
            
            Func1();
            GC.Collect();
            Console.WriteLine("End");
            Console.ReadLine();
        }
        static void Func1()
        {
            A a = new A();
            a.Callback((str)=>Console.WriteLine(str));
        }
        
        static void Callback(Action<string> success)
        {
            Task.Run(() => {
                Task.Delay(10 * 500).Wait();
                success("Ok");//为啥能正常运行,是因为闭包延长了success的作用域么?
            });
        }
    }
    class A 
    {
        public void Func1()
        {
            Callback((str) => Console.WriteLine(str));
        }

       public void Callback(Action<string> success)
        {
            Task.Run(() => {
                Task.Delay(10 * 500).Wait();
                  success.Invoke("Ok");//为啥能正常运行,是因为闭包延长了success的作用域么?
            });
        }
    }

问:Task中为啥success 能正常执行?闭包提升了success引用的方法的作用域么?提升到哪里了?

GYY_顽石的主页 GYY_顽石 | 初学一级 | 园豆:143
提问于:2022-09-30 17:08
< >
分享
所有回答(1)
0

是的。success 能够在 Task 中正常执行,这是因为它被闭包(Closures)捕获了。

在 C# 中,当你在一个方法内部创建一个委托时,并且这个委托引用了该方法的局部变量,那么就会形成一个闭包。闭包可以保留对这些局部变量的引用,即使这些方法已经返回并且其局部作用域已经不存在了。

在你的代码中,Action<string> success 是一个委托,它在 Func1 或者 Callback 方法的作用域中被定义,然后被传给另一个任务去执行。这个任务在其他线程上异步运行,可能在 Func1Callback 方法已经返回之后。由于闭包,这个任务依然能访问 success 并成功调用它。

至于“提升到哪里了”,闭包是将局部变量 "提升" 到了包含这个方法的类的实例级别。所以,只要这个实例还存在,这个变量就可以被访问,不论原始的作用域是否还存在。这有助于理解为什么 GC.Collect() 不会回收这个变量,因为它仍然被包含它的对象引用(即使原来的方法已经返回)。

npe0 | 园豆:1299 (小虾三级) | 2023-12-18 11:42
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册