日期:2014-05-20  浏览次数:20830 次

奇怪的局部变量
奇怪的局部变量:讨论一下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]:输出什么?

------解决方案--------------------
1和2都只输出一个值9,因为都只有一个变量,不同的是拿的地方不同,一个从堆,一个从栈,3应该输出0到9,因为它从九个变量中拿值,只不过变量的名字一样,但地址是不一样的,4应该输出同样的值,因为只有一个变量
------解决方案--------------------
谢lz,以前不知道什么是闭包,因这篇帖子去搜了一下,很有用的东西。感觉本题应该是0、1一样,2、3一样
------解决方案--------------------
其实就是在匿名方法里引用局部变量的问题,当匿名方法里用到的方法体外的某个局部变量被称作外部变量,按msdn说法编译器会给这些外部变量创建引用防止它们的生命周期过早结束,外部变量和一般的局部变量没什么区别,只不过生命周期是随着使用它的匿名方法结束才结束。
所以判断起来很简单,例子0是静态变量,这个结果大家都知道;例子1虽然是局部变量,但是这个局部变量的作用域在main函数内,每次循环都不会结束它的生命周期,所以结果和例子0一样;而例子2是循环内部的局部变量,每次循环都产生一个新的局部变量,那么编译器每次循环都会创建一个新的引用,所以结果是预期中的;至于3是循环变量,和0、1没差别。