这些示例是 C# 闭包吗?

发布于 2024-08-08 14:55:27 字数 868 浏览 3 评论 0原文

我还是不太明白闭包是什么,所以我发布了这两个例子,我想知道这些例子是否都是闭包?

示例 A:

List<DirectoryInfo> subFolders = new List<DirectoryInfo>();

Action<string> FilterSubFoldersStartA =
  s => subFolders.
       AddRange((new DirectoryInfo(s)).GetDirectories().
       Where(d => d.Name.StartsWith("A")));

FilterSubFoldersStartA(@"c:\tempa");
FilterSubFoldersStartA(@"c:\tempb");

示例 B:

List<DirectoryInfo> subFolders = new List<DirectoryInfo>();

string filter = "A";

Action<string> FilterSubFoldersStartGen =
  s => subFolders.
       AddRange((new DirectoryInfo(s)).GetDirectories().
       Where(d => d.Name.StartsWith(filter)));

FilterSubFoldersStartGen(@"c:\tempa");

filter = "B"; 

FilterSubFoldersStartGen(@"c:\tempb");

I still don't quite understand what a closure is so I posted these two examples and I want to know whether these examples are both closures or not?

Example A:

List<DirectoryInfo> subFolders = new List<DirectoryInfo>();

Action<string> FilterSubFoldersStartA =
  s => subFolders.
       AddRange((new DirectoryInfo(s)).GetDirectories().
       Where(d => d.Name.StartsWith("A")));

FilterSubFoldersStartA(@"c:\tempa");
FilterSubFoldersStartA(@"c:\tempb");

Example B:

List<DirectoryInfo> subFolders = new List<DirectoryInfo>();

string filter = "A";

Action<string> FilterSubFoldersStartGen =
  s => subFolders.
       AddRange((new DirectoryInfo(s)).GetDirectories().
       Where(d => d.Name.StartsWith(filter)));

FilterSubFoldersStartGen(@"c:\tempa");

filter = "B"; 

FilterSubFoldersStartGen(@"c:\tempb");

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

如梦 2024-08-15 14:55:27

您的第二个示例使用了闭包(从技术上讲,您可以说编译器在两种情况下都会计算闭包,但在第一种情况下您不会使用它)。

闭包就是“该函数可见的所有变量”。不多不少。显然,在这两种情况下,这些变量都存在,并且由编译器确定。

但是,当我们谈论“使用闭包”时,我们通常的意思是 lambda 表达式可以使用在声明位置可见的所有局部变量。它们都是其关闭的一部分。

在您的例子中,d 只是 lambda 函数的参数,并且由于这就是您在第一种情况下使用的所有内容,因此您并没有真正利用闭包。

在第二种情况下,filter 未在 lambda 表达式中定义,它不是参数或任何内容。它是一个局部变量,恰好在声明 lambda 的地方可见。因此它是 lambda 闭包的一部分,允许您在 lambda 主体中引用它。

编辑
正如评论中指出的,我没有仔细阅读您的代码。我只注意到每个示例中的第二个 lambda 表达式。第一个 lambda 确实使用了闭包(在这两种情况下,它都会通过 subFolders 关闭。)

Your second example makes use of closures (technically you could say that the compiler computes a closure in both cases, but you don't make use of it in the first case).

A closure is simply "all the variables visible to this function". Nothing more, nothing less. And obviously, in both cases, those variables exist, and are determined by the compiler.

But what we usually mean when we talk about "using closures" is that lambda expressions can use all local variables visible at the place they're declared. They're all part of its closure.

In your case, d is simply the parameter to the lambda function, and since that's all you use in the first case, you're not really taking advantage of closures.

In the second case, filter is not defined in the lambda expression, it's not a parameter or anything. It's a local variable which just so happens to be visible at the place where the lambda is declared. So it is part of the lambda's closure, which allows you to reference it in the body of the lambda.

Edit
As pointed out in the comments, I didn't read your code too closely. I only noticed the second lambda expression in each example. The first lambda does use closures (it closes over subFolders in both cases.)

故事与诗 2024-08-15 14:55:27

是的,闭包只不过是一个从定义它的环境中“保存”一些变量的函数。因此,在两个示例中,定义的操作都会保存名为 subFolders 的列表,即使局部变量超出范围,函数也可以引用该列表。第二个示例中的 filter 变量也由定义的函数保存。

更精确的定义此处

Yea, a closure is nothing more than a function that "saves" some variables from the environment in which it is defined. So in both of your examples, the defined action saves the list named subFolders, which can be referenced by the functions even after the local variable is out of scope. The filter variable in the second example is also saved by the defined function.

A more precise definition here

表情可笑 2024-08-15 14:55:27

这两个例子都有闭包。在“A”中,匿名方法捕获局部变量子文件夹。在“B”中,匿名方法捕获局部变量 subFolders 和过滤器。另请查看此处

PS 另请注意,您实际上在“A”中使用了闭包,因为您正在使用 subFolders 变量。

Both examples have closures. In "A" anonymous method captures local variable subFolders. In "B" anonymous method captures local variables subFolders and filter. Also take a look here.

P.S. Also note that you are actually using closure in "A" because you are using subFolders variable.

北斗星光 2024-08-15 14:55:27

以下是 http://www.agileatwork.com/a-proper- 的示例如果您熟悉 JavaScript,那么闭包 in-csharp/ 的内容可能看起来更熟悉一些。围绕 tax 变量创建一个闭包,因此计算仅完成一次。这对眼睛来说并不容易,但是可以在 C# 中完成这种类型的事情很酷。

public class Order
{
    public Order(ITaxCalculator taxCalculator)
    {
        CalculateTax = new Func<Func<decimal>>(() =>
        {
            decimal? tax = null;
            return () =>
            {
                if (!tax.HasValue)
                {
                    tax = taxCalculator.Calculate(this);
                }
                return tax.Value;
            };
        })();
    }

    public Func<decimal> CalculateTax { get; set; }

    ...
}

Here's an example from http://www.agileatwork.com/a-proper-closure-in-csharp/ of something that might look a little more familiar if you're comfortable with JavaScript. A closure is created around the tax variable so the calculation is only done one time. It isn't exactly easy on the eyes, but it's cool that you can do this type of thing in C#.

public class Order
{
    public Order(ITaxCalculator taxCalculator)
    {
        CalculateTax = new Func<Func<decimal>>(() =>
        {
            decimal? tax = null;
            return () =>
            {
                if (!tax.HasValue)
                {
                    tax = taxCalculator.Calculate(this);
                }
                return tax.Value;
            };
        })();
    }

    public Func<decimal> CalculateTax { get; set; }

    ...
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文