存储匿名方法的容器

3
我有以下定义。
type
  TOmniTaskDelegate = reference to procedure(const task: IOmniTask);

我应该使用哪种容器(D2009支持)来存储TOmniTaskDelegate实例的列表?目前我正在使用array of TOmniTaskDelegate,但我并不是很满意。


你为什么对这个数组不满意? - Lasse V. Karlsen
a) 因为我想将责任委托给一个具有明确定义接口的容器。 b) 因为我现在每次添加东西时都要调整数组大小。确实,我可以编写一个很好的包装器来了解当前大小和分配大小等信息,但这样我已经重新实现了TSomeList<T>,我宁愿使用Delphi提供的东西(假设存在这样的东西)。 - gabr
2
什么是 TSomeList<T>?你不能只用 TSomeList<TOmniTaskDelegate> 吗? - David Heffernan
SomeList = 可以是 TList、TObjectList 或者 D2009 中支持的其他类型的列表,我不知道还有哪些。 - gabr
2个回答

8
我会使用 TList<TOmniTaskDelegate>。由于这是一种使用泛型的类型安全方法,因此它将正确处理其成员的生命周期问题。

1
我正在思考 Generics.Collections 中的 TList<T>。它处理引用计数,因为它是类型安全的。但现在我有一个烦人的怀疑,它可能不包含在 D2009 中。 - David Heffernan
1
+1。显然,通用的TList<T>在Delphi 2009中是可用的。无需重新发明轮子:使用array of实现了通用列表,因此保证了正确的终结和类型安全。 - Cosmin Prund
注意一种情况,即您想通过指定引用从列表中删除某些内容。我曾经遇到过这样的情况,因为Delphi每次都会创建不同的魔术自动匿名方法包装器,即使是相同的方法,所以项目没有被删除。 - Heinrich Ulbricht
1
@Heinrich 这是因为它是一个不同的引用。请记住,匿名方法具有变量捕获。 - David Heffernan
1
@David 在对象中添加相同的“方法”多次也会给出不同的引用。第一次遇到这种情况时,我感到很惊讶。我以为它们会是相同的。 - Heinrich Ulbricht
显示剩余3条评论

3

编辑:Delphi 2009 包含泛型 TList<T>,我认为它是使用 array of 实现的,就像 Delphi 2010 中的那个一样。这使得 TList<T> 是最优选择!我的原始答案仍然有效,因为它解释了为什么 array of 是一个很棒的数据结构,以及为什么不使用它会带来很多麻烦。


你的选择 array of Anonym 看起来非常好,因为:

  • 匿名方法是托管实体(使用接口实现)。它们需要被正确地终止。
  • 动态数组本身是一种托管类型,确保匿名方法引用被正确地终止。
  • Delphi 2010 泛型容器使用动态数组实现,所以它们可以胜任这个任务。但一定要确保你不是逐个增加数组大小,而是按块增加。

如果你使用其他东西进行实现,你就需要自己处理引用对象的终止。例如:

  • 如果你使用普通内存块,你需要一个析构函数,有意将每个项目设置为 nil(即不是 ZeroMemory 或 FillChar),这样编译器有机会生成终止代码。
  • 记录是托管对象,它们可以持有对动态方法的引用,但只能持有有限数量的引用,如果你需要更多引用,就需要实现一种链接列表,然后仔细管理它们的生命周期。
  • 类遭受了记录所有缺陷,并在此基础上添加了自己的一层开销。

1
在您的情况下,您正在实现一种基本类型(一种基本的新列表类型),我不相信泛型和编译器可以被信任,以免做出会破坏过程引用的事情。如果我要使用除ProcRef数组之外的其他东西,那么我将使用TList <Record>并将过程引用放在记录类型中。 - Warren P
1
“array of” 对于列表的私有实现来说是可以的,但我不会希望将其用作主要数据类型。如果您无法使用 TList<T>,那么请创建自己的类似对象。 - David Heffernan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接