斗爷

导航

c#闭包(转)

出处:http://www.cnblogs.com/birdwudi/archive/2010/08/20/1804342.html

------------------------------------------------------------------------------

简单来讲,闭包允许你将一些行为封装,将它像一个对象一样传来递去,而且它依然能够访问到原来第一次声明时的上下文

奇怪的局部变量:讨论一下C#中的闭包

[0]静态全局字段

C# code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication3
{
    class Program
    {
        public static int copy;//[0]这个不是闭包
        static void Main()
        {
            //定义动作组
            List<Action> actions = new List<Action>();
            for (int counter = 0; counter < 10; counter++)
            {
                copy = counter;
                actions.Add(() => Console.WriteLine(copy));
            }
            //执行动作
            foreach (Action action in actions) action();
        }
    }
}

//注:Action定义如下:
//public delegate void Action();



[1]局部变量(闭包一)

C# code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication3
{
    class Program
    {
        static void Main()
        {
            int copy;//[1]闭包一
            //定义动作组
            List<Action> actions = new List<Action>();
            for (int counter = 0; counter < 10; counter++)
            {
                copy = counter;
                actions.Add(() => Console.WriteLine(copy));
            }
            //执行动作
            foreach (Action action in actions) action();
        }
    }
}

//注:Action定义如下:
//public delegate void Action();



[2]局部变量(闭包二)

C# code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication3
{
    class Program
    {
        static void Main()
        {
            //定义动作组
            List<Action> actions = new List<Action>();
            for (int counter = 0; counter < 10; counter++)
            {
                int copy;//[1]闭包二
                copy = counter;
                //int copy = counter;//换种写法
                actions.Add(() => Console.WriteLine(copy));
            }
            //执行动作
            foreach (Action action in actions) action();
        }
    }
}

//注:Action定义如下:
//public delegate void Action();



[3]局部变量(闭包三)

C# code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication3
{
    class Program
    {
        static void Main()
        {
            //定义动作组
            List<Action> actions = new List<Action>();
            for (int counter = 0; counter < 10; counter++)//[3]闭包三
            {
                actions.Add(() => Console.WriteLine(counter));
            }
            //执行动作
            foreach (Action action in actions) action();
        }
    }
}

//注:Action定义如下:
//public delegate void Action();



[0]:输出什么?
[1]:输出什么?
[2]:输出什么?
[3]:输出什么?

 

 

这几个例子,可以将匿名函数进行转换,这样可以看的更清楚
在[0]中,“外部变量”copy是类的一个静态成员,因此可以讲匿名函数转换为以下形式:

C# code

    class Program
    {
        public static int copy;//[0]这个不是闭包
        static void TempMethod()
        {
            Console.WriteLine(copy);
        }
        static void Main()
        {
            //定义动作组
            List<Action> actions = new List<Action>();
            for (int counter = 0; counter < 10; counter++)
            {
                copy = counter;
                actions.Add(new Action(TempMethod));
            }
            //执行动作
            foreach (Action action in actions) action();
        }
    }





[1],[2]中“外部变量”copy是Main方法中的局部变量,局部变量的生存期现在必须至少延长为匿名函数委托的生存期。这可以通过将局部变量“提升”到编译器生成的类的字段来实现。之后,局部变量的实例化对应于为编译器生成的类创建实例,而访问局部变量则对应于访问编译器生成的类的实例中的字段。而且,匿名函数将会成为编译器生成类的实例方法:

C# code

    class Program
    {
        static void Main()
        {
            //定义动作组
            TempClass tc = new TempClass();
            //定义动作组
            List<Action> actions = new List<Action>();
            for (int counter = 0; counter < 10; counter++)
            {
                tc.copy = counter;
                actions.Add(tc.TempMethod);
            }
            //执行动作
            foreach (Action action in actions) action();
        }
        class TempClass
        {
            public int copy;
            public void TempMethod()
            {
                Console.WriteLine(copy);
            }
        }
    }




 

C# code

    class Program
    {
        static void Main()
        {
            //定义动作组

            //定义动作组
            List<Action> actions = new List<Action>();
            for (int counter = 0; counter < 10; counter++)
            {
                TempClass tc = new TempClass();
                tc.copy = counter;
                actions.Add(tc.TempMethod);
            }
            //执行动作
            foreach (Action action in actions) action();
        }
        class TempClass
        {
            public int copy;
            public void TempMethod()
            {
                Console.WriteLine(copy);
            }
        }
    }




[3]中的“外部变量”counter是for循环的循环因子,因此可以转换为以下形式:

C# code

    class Program
    {
        static void Main()
        {
            //定义动作组
            List<Action> actions = new List<Action>();
            TempClass tc = new TempClass();
            for (tc.copy = 0; tc.copy < 10; tc.copy++)
            {
                actions.Add(new Action(tc.TempMethod));
            }
            //执行动作
            foreach (Action action in actions) action();
        }
        class TempClass
        {
            public int copy;
            public void TempMethod()
            {
                Console.WriteLine(copy);
            }
        }
    }

 

 

posted on 2016-12-08 09:46  斗哥哥  阅读(296)  评论(0编辑  收藏  举报