匿名方法 - 可变捕获与值捕获 [英] Anonymous methods - variable capture versus value capture

查看:143
本文介绍了匿名方法 - 可变捕获与值捕获的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面是基于Chris Rolliston优秀的Delphi XE2 Foundations书第1部分
的匿名方法部分中的一个示例,关于变量
捕获的想法(任何错误都完全失效对我而言。

Below is a SSCCE based on an example in the Anonymous Methods section of Part 1 of Chris Rolliston's excellent Delphi XE2 Foundations book, about the idea of variable capture (any errors in it are entirely down to me).

它的工作原理与我预期的一样,在连续点击
BtnInvoke按钮时记录666,667,668,669。特别是,它很好地说明了btnSetUpClick退出之后,
本地变量的捕获版本如何持久存在。

It works exactly as I'd expect, logging 666, 667, 668, 669 on successive clicks of the BtnInvoke button. In particular it nicely illustrates how the captured version of the local variable I persists long after btnSetUpClick exits.

到目前为止这么好。我问的问题不在于这个代码本身,而是
在Allen Bauer的博客中有这样的说法:

So far so good. The problem I'm asking about isn't with this code per se but with what's said in Allen Bauer's blog here:

http://blogs.embarcadero.com/abauer/2008/10/15/38876

现在,我比老板更好地知道,所以我相信我错过了他在变量捕获和价值捕获之间绘制的区别
。以简单的方式
查看它,我的基于CR的示例通过捕获我作为一个变量捕获我的价值。

Now, I know better than to argue with the boss, so I am sure I'm missing the point of the distinction he draws between variable capture and value capture. To my simple way of looking at it, my CR-based example captures the value of I by capturing I as a variable.

所以,我的问题是Bauer先生试图绘制的区别是什么?

So, my question is, what is the distinction Mr Bauer is trying to draw, exactly?

(Btw,尽管每天都在观看德尔福部分超过9个月的时间,但我还没有完全
清楚,如果这个q是主题的话,如果没有,我的道歉,我会把它放下。)

(Btw, despite watching the Delphi section of SO daily for 9+ months, I'm still not entirely clear if this q is on-topic. If not, my apologies and I'll take it down.)

type
  TAnonProc = reference to procedure;

var
  P1,
  P2 : TAnonProc;

procedure TForm2.Log(Msg : String);
begin
  Memo1.Lines.Add(Msg);
end;

procedure TForm2.btnSetUpClick(Sender: TObject);
var
  I : Integer;
begin
  I := 41;
  P1 := procedure
    begin
      Inc(I);
      Log(IntToStr(I));
    end;

  I := 665;
  P2 := procedure
    begin
      Inc(I);
      Log(IntToStr(I));
    end;
end;

procedure TForm2.btnInvokeClick(Sender: TObject);
begin
  Assert(Assigned(P1));
  Assert(Assigned(P2));

  P1;
  P2;
end;


推荐答案

变量捕获与值捕获非常简单。让我们假设两个匿名方法捕获相同的变量。像这样:

Variable capture vs value capture is simple enough. Let us suppose that two anonymous methods capture the same variable. Like this:

Type
  TMyProc = reference to procedure;
var
  i: Integer;
  P1, P2: TMyProc;
....
i := 0;
P1 := procedure begin Writeln(i); inc(i); end;
P2 := procedure begin Writeln(i); inc(i); end;
P1();
P2();
Writeln(i);

有两个方法捕获的单个变量。输出是:

There is a single variable that is captured by both methods. The output is:


0
1
2

这是一个变量的捕获。如果该值被捕获,哪一个不是,那么可能会想到这两个方法会有单独的变量,它们都以值为0的值开始。这两个函数都可能会输出0.

This is capture of a variable. If the value was captured, which it isn't, one might imagine that the two methods would have separate variables that both started with value 0. And both functions might output 0.

在你的例子中,你应该想象, P1 捕获值 41 P2 捕获值 665 。但这不会发生。只有一个变量。它在声明它的过程和捕获它的匿名方法之间共享。只要分享它的所有各方活着就会生活。所有其他方面都会看到对一方作出的变量的修改,因为只有一个变量。

In your example, you are supposed to imagine that P1 captures the value 41, and P2 captures the value 665. But that does not happen. There is exactly one variable. It is shared between the procedure that declares it, and the anonymous methods that capture it. It lives as long as all parties that share it live. Modifications to the variable made by one party are seen by all others because there is exactly one variable.

所以,不可能捕获一个值。要获得感觉到需要将值复制到新变量并捕获该新变量的行为。这可以通过一个参数来完成。

So, it is not possible to capture a value. To get behaviour that feels like that you need to copy a value to a new variable, and capture that new variable. That can be done with, for instance, a parameter.

function CaptureCopy(Value: Integer): TMyProc;
begin
  Result := procedure begin Writeln(Value); end;
end;

...
P3 := CaptureCopy(i);

这将将 i 的值复制到一个新变量,过程参数,并捕获。后续更改 i P3 没有影响,因为捕获的变量是 P3

This will copy the value of i into a new variable, the procedure parameter, and capture that. Subsequent changes to i have no influence on P3 because the captured variable is local to P3.

这篇关于匿名方法 - 可变捕获与值捕获的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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