什么时候使用闭包? [英] When to use closure?

查看:57
本文介绍了什么时候使用闭包?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我看到了来自以下方面的关闭示例 - 什么是关闭"?>

谁能提供何时使用闭包的简单示例?

具体来说,在哪些情况下关闭有意义?

假设该语言没有闭包支持,如何实现类似的功能?

为了不冒犯任何人,请以 c#、python、javascript、ruby 等语言发布代码示例.
对不起,我还不懂函数式语言.

解决方案

闭包只是很棒的工具.什么时候使用它们?任何时候你喜欢...... 正如已经说过的,另一种选择是编写一个类;例如,在 C# 2.0 之前,创建参数化线程是一场真正的斗争.使用 C# 2.0,您甚至不需要ParameterizedThreadStart",您只需要做:

string name =//等等int value =//等等new Thread((ThreadStart)delegate { DoWork(name, value);});//或内联,如果很短

将其与创建具有名称和值的类进行比较

或者同样搜索列表(这次使用 lambda):

Person person = list.Find(x=>x.Age > minAge && x.Region == region);

再次 - 另一种方法是编写一个具有两个属性和一个方法的类:

内部密封类PersonFinder{public PersonFinder(int minAge,字符串区域){this.minAge = minAge;this.region = 区域;}私有只读 int minAge;私有只读字符串区域;public bool IsMatch(人){返回人.年龄>最小年龄&&person.Region == 区域;}}...Person person = list.Find(new PersonFinder(minAge,region).IsMatch);

这与编译器在引擎盖下的操作方式相当(实际上,它使用公共读/写字段,而不是私有只读字段).

C# 捕获的最大警告是观察范围;例如:

 for(int i = 0 ; i <10 ; i++) {ThreadPool.QueueUserWorkItem(委托{Console.WriteLine(i);});}

这可能不会打印您期望的内容,因为 变量 i 用于每个变量.您可以看到任何重复组合 - 甚至 10 个 10.您需要在 C# 中仔细确定捕获的变量的范围:

 for(int i = 0 ; i <10 ; i++) {int j = i;ThreadPool.QueueUserWorkItem(委托{Console.WriteLine(j);});}

这里每个 j 被单独捕获(即不同的编译器生成的类实例).

Jon Skeet 有一篇很好的博客文章,涵盖了 C# 和 Java 闭包 这里;或更多详细信息,请参阅他的书C# in Depth,其中有一整章介绍了这些内容.>

I have seen samples of closure from - What is a 'Closure'?

Can anyone provide simple example of when to use closure?

Specifically, scenarios in which closure makes sense?

Lets assume that the language doesn't have closure support, how would one still achieve similar thing?

Not to offend anyone, please post code samples in a language like c#, python, javascript, ruby etc.
I am sorry, I do not understand functional languages yet.

解决方案

Closures are simply great tools. When to use them? Any time you like... As has already been said, the alternative is to write a class; for example, pre C# 2.0, creating a parameterised thread was a real struggle. With C# 2.0 you don't even need the `ParameterizedThreadStart' you just do:

string name = // blah
int value = // blah
new Thread((ThreadStart)delegate { DoWork(name, value);}); // or inline if short

Compare that to creating a class with a name and value

Or likewise with searching for a list (using a lambda this time):

Person person = list.Find(x=>x.Age > minAge && x.Region == region);

Again - the alternative would be to write a class with two properties and a method:

internal sealed class PersonFinder
{
    public PersonFinder(int minAge, string region)
    {
        this.minAge = minAge;
        this.region = region;
    }
    private readonly int minAge;
    private readonly string region;
    public bool IsMatch(Person person)
    {
        return person.Age > minAge && person.Region == region;
    }
}
...
Person person = list.Find(new PersonFinder(minAge,region).IsMatch);

This is fairly comparable to how the compiler does it under the bonnet (actually, it uses public read/write fields, not private readonly).

The biggest caveat with C# captures is to watch the scope; for example:

        for(int i = 0 ; i < 10 ; i++) {
            ThreadPool.QueueUserWorkItem(delegate
            {
                Console.WriteLine(i);
            });
        }

This might not print what you expect, since the variable i is used for each. You could see any combination of repeats - even 10 10's. You need to carefully scope captured variables in C#:

        for(int i = 0 ; i < 10 ; i++) {
            int j = i;
            ThreadPool.QueueUserWorkItem(delegate
            {
                Console.WriteLine(j);
            });
        }

Here each j gets captured separately (i.e. a different compiler-generated class instance).

Jon Skeet has a good blog entry covering C# and java closures here; or for more detail, see his book C# in Depth, which has an entire chapter on them.

这篇关于什么时候使用闭包?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆