Closed. This question needs to be more focused。它当前不接受答案。
想改善这个问题吗?更新问题,使其仅通过editing this post专注于一个问题。
2年前关闭。
当我运行此代码时:
打印的内容是:
B3B2B1C30C20C10C31C21C32
谁能给我解释为什么打印出来?
您可以忘记先前将
同样,当您执行
还要注意,本地函数现在可能是一种更好且更清晰的方式来执行此类操作。
让我们看看实际发生了什么。我们从开始:
并调用
(这意味着它先运行一个方法,然后再运行另一个方法),并注意第二个委托中的
现在我们调用
(请注意,我已经像以前一样固定了参数的值),然后执行
在执行此操作之前……请记住,我们仍有待执行的
因此:
(再次,注意我固定的价值)。我们再次使用
使用
第一部分没有做任何事情,但是我们确实有三个后缀可以与
想改善这个问题吗?更新问题,使其仅通过editing this post专注于一个问题。
2年前关闭。
当我运行此代码时:
string x = "";
Action<int> myAction = (i) => x += ("A" + i);
myAction = (i) =>
{
if (i > 0)
{
x += ("B" + i);
myAction += (i2) => x += ("C" + i + i2);
myAction(i - 1);
}
};
myAction(3);
Console.WriteLine(x);
打印的内容是:
B3B2B1C30C20C10C31C21C32
谁能给我解释为什么打印出来?
最佳答案
请注意,一旦您这样做:
myAction = ....
您可以忘记先前将
myAction
设置为的内容;现在已经输给了以太。您可能还已经初始化了Action<int> myAction = null;
。关键是要捕获变量myAction
-而不是其值。因此,第二个委托中的代码正在调用自身,而不是涉及“ A”的代码。同样,当您执行
myAction += (i2) => x += ("C" + i + i2);
时,您将更改所有后续代码的委托。还要注意,本地函数现在可能是一种更好且更清晰的方式来执行此类操作。
让我们看看实际发生了什么。我们从开始:
myAction = (i) =>
{
if (i > 0)
{
x += ("B" + i);
myAction += (i2) => x += ("C" + i + i2);
myAction(i - 1);
}
};
并调用
myAction(3)
。 i>0
,因此x
变为“ B3”。现在我们做一些复杂的事情-我们结合了两个委托,所以myAction
现在是:myAction = (i) =>
{
if (i > 0)
{
x += ("B" + i);
myAction += (i2) => x += ("C" + i + i2);
myAction(i - 1);
}
} + (i2) => x += ("C" + i + i2);
(这意味着它先运行一个方法,然后再运行另一个方法),并注意第二个委托中的
i
是上一个调用中的参数i
。由于该参数不变,因此我们可以名义上对其进行修复(尽管实际上它是一个捕获上下文字段),并说:myAction = (i) =>
{
if (i > 0)
{
x += ("B" + i);
myAction += (i2) => x += ("C" + i + i2);
myAction(i - 1);
}
} + (i2) => x += ("C" + 3 + i2);
现在我们调用
myAction(i - 1 === 2);
。很好-让我们依次执行这两部分;第一部分找到i>0
,因此x变为“ B3B2”。现在我们重写myAction
,使其变为三倍:myAction = (i) =>
{
if (i > 0)
{
x += ("B" + i);
myAction += (i2) => x += ("C" + i + i2);
myAction(i - 1);
}
} + (i2) => x += ("C" + 3 + i2)
+ (i2) => x += ("C" + 2 + i2);
(请注意,我已经像以前一样固定了参数的值),然后执行
myAction(i - 1)
。在执行此操作之前……请记住,我们仍有待执行的
(i2) => x += ("C" + 3 + i2);
待执行,但稍后会发生(稍后我将其称为“ PendingA”)。由于委托是不可变的,因此我们为委托分配新值不会影响该挂起的执行。因此:
i2=2
:再次,myAction(i-1 === 1)
使得i>0
变为“ B3B2B1”,我们再次更改了委托:myAction = (i) =>
{
if (i > 0)
{
x += ("B" + i);
myAction += (i2) => x += ("C" + i + i2);
myAction(i - 1);
}
} + (i2) => x += ("C" + 3 + i2)
+ (i2) => x += ("C" + 2 + i2);
+ (i2) => x += ("C" + 1 + i2);
(再次,注意我固定的价值)。我们再次使用
x
调用它,首先要注意我们有一个待处理的: (i2) => x += ("C" + 3 + i2)
+ (i2) => x += ("C" + 2 + i2); // call this PendingB
使用
myAction(i-1) === 0
以便稍后展开时运行。第一部分没有做任何事情,但是我们确实有三个后缀可以与
i2===1
一起运行。因此我们得到(依次应用)“ B3B2B1C30C20C10”。至此,我们已经完成了工作-我们已经达到了栈底。现在我们需要展开!我们有一个待办事项双脚跑。展开时,“ PendingB”首先出现,这使i2===0
变为“ B3B2B1C30C20C10C31C21”;然后“ PendingA”给我们“ B3B2B1C30C20C10C31C21C32”关于c# - 引用并添加到自身的C#委托(delegate),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44312394/
10-08 22:31