代码之家  ›  专栏  ›  技术社区  ›  Edward Tanguay

闭包有什么特别的?

  •  12
  • Edward Tanguay  · 技术社区  · 16 年前

    我一直在 reading this article about closures 他们说:

    • “所有管道都是自动的”
    • 编译器“创建包装类”和“扩展变量的寿命”
    • “您可以不用担心地使用局部变量”
    • .NET编译器为您处理管道等。

    因此,我根据它们的代码做了一个例子,在我看来,闭包的作用类似于常规的命名方法,这些方法“无需担心地处理局部变量”,“所有管道都是自动的”。

    或者,这种“局部变量包装”解决了什么问题,使得闭包如此特殊/有趣/有用?

    using System;
    namespace TestingLambda2872
    {
        class Program
        {
            static void Main(string[] args)
            {
                Func<int, int> AddToIt = AddToItClosure();
    
                Console.WriteLine("the result is {0}", AddToIt(3)); //returns 30
                Console.ReadLine();
            }
    
            public static Func<int, int> AddToItClosure()
            {
                int a = 27;
                Func<int, int> func = s => s + a;
                return func;
            }
        }
    }
    

    回答

    所以这个问题的答案是 Jon Skeet's article on closures 马克指出。本文不仅展示了C语言中lambda表达式的演变过程,还展示了如何在Java中处理闭包,这是本主题的一个极好的读法。

    2 回复  |  直到 16 年前
        1
  •  20
  •   Marc Gravell    16 年前

    您的示例不清楚,并且(imo)没有显示典型的捕获用法(捕获的唯一内容是 a ,总是3个,所以不是很有趣)。

    考虑下面的课本示例(谓词):

    List<Person> people = ...
    string nameToFind = ...
    Person found = people.Find(person => person.Name == nameToFind);
    

    现在尝试它而不关闭;您需要做更多的工作,即使我们是懒惰的:

    PersonFinder finder = new PersonFinder();
    finder.nameToFind = ...
    Person found = people.Find(finder.IsMatch);
    ...
    class PersonFinder {
        public string nameToFind; // a public field to mirror the C# capture
        public bool IsMatch(Person person) {
            return person.Name == nameToFind;
        }
    }
    

    捕获方法进一步扩展到不同范围的许多变量-a 许多 隐藏的复杂性。

    除了名称之外,上面是C编译器在幕后所做工作的近似值。注意,当涉及到其他范围时,我们开始链接不同的捕获类(即内部范围引用了外部范围的捕获类)。相当复杂。

    乔恩·斯基特有一个很好的 article on this here 以及更多 in his book .

        2
  •  0
  •   Stefan Steinegger    16 年前

    闭包是编译器的一个功能。你看不到它,它只是让你写的代码工作。

    如果没有它,对addtoit(3)的调用将失败,因为基础lamda在addtoitclusure()范围内使用局部变量a=27。调用addToIt时,此变量不存在。

    但是由于这个闭包是编译器使用的一种机制,所以代码可以工作,您不必关心它。