大学IT网 - 最懂大学生的IT学习网站! QQ资料交流群:367606806
当前位置:大学IT网 > C#技巧 > 委托、Lambda表达式、事件系列05,Action委托与闭包

委托、Lambda表达式、事件系列05,Action委托与闭包

关键词:委托Lambda表达式事件  阅读(786) 赞(18)

[摘要]本文是对委托、Lambda表达式、事件系列05,Action委托与闭包的讲解,对学习C#编程技术有所帮助,与大家分享。

来看使用Action委托的一个实例:

static void Main(string[] args)

        {

            int i = 0;

            Action a = () => i++;

            a();

            a();

            Console.WriteLine(i);

        }

12

结果是期望能的2。但令人好奇的是:栈上的变量i是如何传递给Action委托的?

反编译进行查看,首先看Main方法对应的IL代码:

13

再看c_DisplayClass1的IL代码:

14

从中可以看出:
→在托管堆上创建了一个名为c_DisplayClass1的实例
→把栈上变量i的值赋值给了c_DisplayClass1的实例字段i
→编译器() => i++;Lambda表达式表示的匿名委托起了个<Main>b_0的方法名,并成为了c_DisplayClass1的实例方法
→把c_DisplayClass1的实例方法<Main>b_0赋值给Action委托变量
→最后调用委托2次,这2次都是针对c_DisplayClass1的实例字段i

换句话说,在托管堆上创建了对象实例,形成"闭包"。栈上的变量变成了闭包的实例字段,Lambda表达式所表示的匿名委托变成了闭包的实例方法。

以上,创建了一个Action,形成了一个"闭包",接下来创建2个Action,形成2个"闭包",看"闭包"的实例字段是否相互影响?

static void Main(string[] args)

        {

            Action a = GetAction();

            Action b = GetAction();


            Console.Write("第一次调用a,i的值=");

            a();

            Console.WriteLine();


            Console.Write("第二次调用a,i的值=");

            a();

            Console.WriteLine();


            Console.Write("第一次调用b,i的值=");

            b();

            Console.WriteLine();

        }


        static Action GetAction()

        {

            Action result = null;

            int i = 0;


            result = () => Console.Write(i++);

            return result;          

        }

15

以上,虽然是把同一个GetAction方法分别赋值给了Action委托,但GetAction方法分别在不同的"闭包"内,当调用委托执行GetAction方法的时候,各自对闭包内的实例字段i自增1并打印,相互间不影响。

总结:每个Action都有自己的"闭包",并且"闭包"间互不影响。



相关评论