关闭行为 [英] Closures behavior

查看:61
本文介绍了关闭行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

This function returns two different values depending on the way its called. I understand that Closures close over variables, not over values and I expected the values returned from the second call to be the same regardless of how the function is called

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的结果:

The result of using Invoke:

4
6

使用赋值变量的结果:

4
7

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

Why does using Invoke changes the closures behavior?

推荐答案

每次调用 Sum ,您正在创建一个单独的 test 委托,以关闭新的 test 变量。区别不是您是否使用 Invoke ,而是您是否正在使用对 Sum()

Each time you call Sum, you're creating a separate test delegate closing over a new test variable. The difference isn't "whether or not you use Invoke" but "whether you're using the result of a new call to Sum().

为证明这一点,您可以将呼叫更改为:

To demonstrate this, you can just change your calls to:

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();

或者您可以致电总和每次:

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();

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

Of course you don't need any parameters to demonstrate this:

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

这篇关于关闭行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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