我将这个回答单独列出来,因为你的编辑使得问题变得非常不同。
稍后我可能会扩展这个答案,因为我现在有点赶着去见客户。
你的编辑表明你需要重新考虑值类型、引用类型以及 var、out、const 和没有参数标记的影响。
首先让我们来看看值类型的事情。
值类型的值存储在堆栈上,并具有复制赋值行为。(稍后我会尝试包含一个例子)。
当你没有参数标记时,传递给方法(过程或函数)的实际值将被复制到该方法内部参数的本地值中。因此,该方法不是对传递给它的值进行操作,而是对其副本进行操作。
当你使用 out、var 或 const 时,就不会发生复制:方法将引用传递的实际值。对于 var,它将允许你更改该实际值,对于 const,它将不允许更改。对于 out,你将无法读取实际值,但仍然可以写入实际值。
引用类型的值存储在堆上,因此对于它们来说,是否有 out、var、const 或没有参数标记几乎没有关系:当你改变某些东西时,你就改变了堆上的值。
对于引用类型,如果没有参数标记,仍然会得到一个副本,但这是指向堆上值的引用的副本。
这就是匿名方法变得复杂的地方:它们进行变量捕获。
(Barry可能可以更好地解释这一点,但我会尝试解释一下)
在您编辑的情况下,匿名方法将捕获List的本地副本。匿名方法将在该本地副本上工作,从编译器的角度来看,一切都很好。
然而,您编辑的关键是“它适用于普通参数”和“谁保证引用在匿名方法执行时仍然指向一个活动对象”。
无论是否使用匿名方法,这始终是引用参数的问题。
例如:
procedure TMyClass.AddObject(Value: TObject);
begin
FValue := Value;
end;
procedure TMyClass.DoSomething();
begin
ShowMessage(FValue.ToString());
end;
谁能保证当有人调用DoSomething时,FValue指向的实例仍然存在?答案是你必须自己保证这一点,方法是在FValue实例死亡时不调用DoSomething。同样的道理也适用于你的编辑:当基础实例已经死亡时,你不应该调用匿名方法。
这是其中一个使用引用计数或垃圾回收解决方案可以使生活更轻松的领域:在那里,实例将被保持活动状态,直到对它的最后一个引用消失(这可能会导致实例的寿命比您最初预期的要长!)。
因此,通过你的编辑,你的问题实际上从匿名方法转变为使用引用类型参数和生命周期管理的影响。
希望我的答案能帮助你在这个领域前进。
--jeroen