c# - 闭包行为

标签 c# .net closures

此函数根据其调用方式返回两个不同的值。 我知道闭包关闭变量,而不是值,我希望无论函数如何调用,第二次调用返回的值都是相同的

static Func<int, int,int> Sum()
{
    var test = 1;
    return (op1, op2) =>
    {
        test = test + 1;

        return (op1 + op2) + test;
    };
}

调用如下:

var mFunc = Sum();
Console.WriteLine("Calling Sum(1,1) with Invoke() " +   Sum().Invoke(1, 1));
Console.WriteLine("Calling Sum(2,2) with Invoke() " + Sum().Invoke(2, 2));

Console.WriteLine("Calling mFunc(1,1)" + mFunc(1, 1));
Console.WriteLine("Calling mFunc(2,2)" + mFunc(2, 2));
Console.Read();

使用Invoke的结果:

4
6

使用赋值变量的结果:

4
7

为什么使用 Invoke 会改变闭包行为?

最佳答案

每次调用 Sum 时,您都会创建一个单独的 test 委托(delegate)来关闭新的 test 变量。区别不是“您是否使用 Invoke”,而是“您是否正在使用对 Sum() 的新调用的结果。

为了演示这一点,您只需将调用更改为:

var mFunc = Sum();
Console.WriteLine("Calling mFunc(1,1) with Invoke() " + mFunc.Invoke(1, 1));
Console.WriteLine("Calling mFunc(2,2) with Invoke() " + mFunc.Invoke(2, 2));
Console.WriteLine("----------");
Console.WriteLine("Calling mFunc(1,1)" + mFunc(1, 1));
Console.WriteLine("Calling mFunc(2,2)" + mFunc(2, 2));
Console.Read();

或者您可以改为每次调用 Sum:

var mFunc = Sum();
Console.WriteLine("Calling Sum()(1,1) with Invoke() " + Sum().Invoke(1, 1));
Console.WriteLine("Calling Sum()(2,2) with Invoke() " + Sum().Invoke(2, 2));
Console.WriteLine("----------");
Console.WriteLine("Calling Sum()(1,1)" + Sum()(1, 1));
Console.WriteLine("Calling Sum()(2,2)" + Sum()(2, 2));
Console.Read();

当然你不需要任何参数来证明这一点:

static Action Increment()
{
    int test = 1;
    return () =>
    {
        Console.WriteLine(test);
        test++;
    };
}

然后:

// New delegate for each call
Increment()(); // Prints 1
Increment()(); // Prints 1 again
Increment()(); // Prints 1 again

// Same delegate three times
var action = Increment();
action(); // Prints 1
action(); // Prints 2
action(); // Prints 3

关于c# - 闭包行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22412734/

相关文章:

c# - 使用重载构造函数时对象实例化失败

c# - 利用 BackGroundWorker 跨线程调用 Winforms 控件上的 GUI 操作?

php - 在别处定义的匿名函数中使用变量

c++ - 为什么委托(delegate)或闭包通常被称为 true "object-oriented function pointers"?

c# - 线程中使用的 DataTable 内部索引已损坏 : '5' .

java - groovy 中的闭包与 java 8 中的闭包(lambda 表达式)?

c# - 比较数据表和合并更改

c# - 根据 C# 中列模式注释的内容从 MySQL 表中选择数据

c# - 如何进行延续并将其作为 MULTI 命令的一部分包含在内?

c# - Linq 中的索引