我一直在迁移Delphi 7中开发的项目,并且每次以前的开发人员想要使用他们创建的集合时都会查看代码:
ArrayOfString : array of string;
ArrayOfInteger: array of integer;
ArrayOfStringArrays : array of ArrayOfString;
这种代码在很多地方都会重复,而且每次都会为它们中的每一个重复“SetLength”,我想知道是否将所有这Array of Something
更改为TList<Something>
现在我们在Delphi中XE4。
这样做有什么好处,资源,速度或类似的东西可以支持我做出这个决定?
PS:我来自JAVA和Delphi给我感到黑暗和充满恐惧答案 0 :(得分:10)
将动态数组视为低于TStringList
或TList<T>
的低级构造。
动态数组通过指针提供对元素的直接访问。该语言隐藏了指针,但基本上所有的动态数组都是。但是你负责任何重新分配,如果你想插入或删除项目,那么你必须编写代码,并处理细节。
更高级别的集合类TStringList
和TList<T>
构建在动态数组之上。这是内部如何存储内容。但是集合类为你包装了这个。作为方法提供了诸如插入和删除等更高级别的操作。实质上,这些集合类比原始动态数组提供了更多的便利。
为了说明,请考虑插入项目的行为。对于动态数组,您可以这样做:
如果您需要多次编写此代码,那么,您做错了。
对于你写的高级集合:
List.Insert(Index, Value);
让课程处理细节。
请注意,由于历史原因,并且因为字符串特别重要,开发人员倾向于使用定制的专用TStringList
类而不是TList<string>
。同样,专用类提供了TList<string>
之外的功能,因为它专门用于字符串,并且可以提供定制到字符串的功能。同样,专用课程提供了便利。
动态阵列派上用场的一个地方就是当你不想招致终身管理的样板时。因此,对于没有针对类的ARC的桌面编译器,您需要明确销毁TList<T>
个实例。但动态阵列的生命周期由ARC管理。如果您一次性合成数组,然后不调整它们的大小,那么生命周期管理问题可以使数组更方便使用。
根据经验,喜欢高级集合类。它们应该是您的默认选择。有时动态数组是正确的选择,但这往往适用于更专业的场景。
答案 1 :(得分:6)
首先,在较新版本的Delphi中,有TArray<T>
类型可用于替换所有旧的array of whatever
声明。使用它可以解决语言中的一些长期陷阱,从经典的Pascal遗留下来,并帮助你不要遇到混乱的错误。
话虽如此,TStringList不是字符串数组;它是一个容器对象,它包含一个字符串列表。它有几种专门的字符串列表处理方法,使它非常通用:它基本上可以用作字符串列表,一组字符串(通过.Sorted
属性),一个字符串/对象映射(通过.Objects
属性)和字符串/字符串映射(通过.Names
和.Values
属性。)
如果您发现您在阵列上大量调用SetLength
,特别是如果它类似于以下内容,您肯定应该将其转换为列表类:
for i := 0 to Count - 1 do
begin
SetLength(myArray, length(myArray) + 1);
myArray[high(myArray)] := values[i];
end;
使用通用TList<T>
或TStringList
,这将成为:
for i := 0 to Count - 1 do
begin
myList.Add(values[i]);
end;
这既易于阅读又具有更高的性能(尤其是具有较大的Count值),因为列表类能够在内部跟踪它们的大小并保持内存重新分配。所以列表类在大多数情况下都是双赢的。在某些情况下,您更喜欢动态数组,但它们很少见。
有一件事需要注意:如果您来自Java背景,请记住动态数组是编译器管理的类型,但列表类是需要在代码中释放的对象。
答案 2 :(得分:0)
除非您特别需要和String of String,否则我强烈建议使用TStringList。我个人根本不会使用TList。 TStringList提供了我所需要的一切,只有少数情况需要求助于一个字符串数组。
可以通过myStringList.Items [i]或者甚至只是myStringList [i]来访问TStringList,就像数组一样。
你不需要保持更改长度或保持计数,你只需要myStringList.Add(aString)和myStringList.Count(不要忘记循环的-1)。
它还具有所有列表操作所需的例程,用于添加,删除,重新排序,排序等。
它也可以作为参数传递,而不需要像数组类型那样的其他声明。
希望这有帮助。