(原创)Delphi2009初体验 - 语言篇 - 体验泛型(一)
2008-08-22 18:11
369 查看
快速导航:
一、概述
二、体验TList<T>
三、体验TObjectList<T>
四、TList<T>和TObjectList<T>的区别
五、后记
Delphi2009提供了几个好用的泛型容器,如TList<T>、TQueue<T>、TStack<T>、TDictionary<TKey, TValue>,还有针对于对象使用的TObjectList<T>等几个类。此外,还提供了TArray数组辅助静态类,封装了数组(array of T)的几个常用操作,如排序等。
但是在智能感知的时候,TList<T>等泛型集合提示好像有些BUG:
program TestTList;
2
3{$APPTYPE CONSOLE}
4
5uses
6 SysUtils,
7 Classes,
8 Generics.Collections; // 泛型集合命名空间,太优美了!
9
var
intList: TList<Integer>;
oldList: TList;
n, elem: Integer;
pTmp: Pointer;
begin
// 以下代码测试旧的集合对象
oldList := TList.Create;
oldList.Add(Pointer(1));
oldList.Add(Pointer(2));
oldList.Add(Pointer(3));
Writeln('TList start');
for n := 0 to oldList.Count - 1 do
begin
Writeln(Integer(oldList
));
end;
for pTmp in oldList do
begin
Writeln(Integer(pTmp));
end;
FreeAndNil(oldList);
// 以下代码测试整形泛型集合对象
intList := TList<Integer>.Create;
intList.Add(1);
intList.Add(2);
intList.Add(3);
Writeln( #13 + #10 + 'TList<T> start');
for n := 0 to intList.Count - 1 do
begin
Writeln(intList
);
end;
for elem in intList do
begin
Writeln(elem);
end;
FreeAndNil(intList);
// ----------------------------------------------------------
Writeln('press any key Readln;
end.
运行结果:
program TestTObjectList;
2
3{$APPTYPE CONSOLE}
4
5uses
6 SysUtils,
7 Contnrs,
8 Generics.Collections,
9 Felix in 'Felix.pas';
var
objList: TObjectList<TFelix>;
oldObjList: TObjectList;
n: Integer;
felix: TFelix;
pFelix: Pointer;
begin
// 以下代码测试旧对象集合
Writeln('TObjectList start');
oldObjList := TObjectList.Create; // 1*
for n := 0 to 2 do
begin
oldObjList.Add(TFelix.Create);
end;
for pFelix in oldObjList do
begin
Writeln(TFelix(pFelix).Id);
end;
FreeAndNil(oldObjList);
// 以下代码测试泛型对象集合
Writeln(#13 + #10 + 'TObjectList<T> start');
objList := TObjectList<TFelix>.Create; // 2*
for n := 0 to 2 do
begin
objList.Add(TFelix.Create);
end;
for felix in objList do
begin
Writeln(felix.Id);
end;
FreeAndNil(objList);
// ----------------------------------------------------------
Writeln('press any key Readln;
end.
![](http://images.cnblogs.com/cnblogs_com/felixyeou/Delphi/%E4%BD%93%E9%AA%8C%E6%B3%9B%E5%9E%8B/p3.gif)
图3
如果我们将代码中的第1*处修改成:
oldObjList := TObjectList.Create(False);
将产生如下结果:
![](http://images.cnblogs.com/cnblogs_com/felixyeou/Delphi/%E4%BD%93%E9%AA%8C%E6%B3%9B%E5%9E%8B/p4.gif)
图4
相对于TObjectList<T>,没有Create(AOwnsObjects: Boolean)方式的重载,我们如何才能让TObjectList<T>“不拥有”对象,当TObjectList<T>中的元素重新赋值、TObjectList<T>集合对象销毁的时候,怎样能保证里面的旧元素不进行销毁操作呢?答案是:不能。
原因在于,TObjectList<T>从TList<T>继承而来,只重写了Notify方法,此方法在集合内元素改变(指针变换、删除、添加)等操作时调用。
请阅读Generics.Collections.pas文件第1236行,TObjectList<T>重写了Notify方法后,先调用了超类的Notify方法,然后判断操作如果为cnRemoved则将元素.Free,所以元素在此处被析构。
受Symbian编程的影响,我习惯于对象自己创建、对象自己销毁,特别是在使用对象集合类,有时候一个对象可能在这个集合内,同时又在另外一个集合内。如果TObjectList<T>把对象销毁了,在另外一个集合内使用对象会造成不可预料的后果,所以建议大家不要使用TObjectList<T>。
其他几个泛型类TDictionary<>等,方法和代码都和.net的类似,看了看代码,真是让人遐想连篇,此处不再介绍。
一、概述
二、体验TList<T>
三、体验TObjectList<T>
四、TList<T>和TObjectList<T>的区别
五、后记
一、概述
等了几百年,Delphi终于原生的支持泛型了。以前使用Delphi,泛型是不被支持的,但是可以用一些第三方库来实现间接的泛型容器支持。如HouSisong大虾编制的DGL泛型库,只需要创建几个简单的“头”文件,就可以拥有指定类型的容器集合类。DGL泛型库非常类似于STL泛型库,很容易上手,如果大家想知道具体使用方法,我另外开文章说明。Delphi2009提供了几个好用的泛型容器,如TList<T>、TQueue<T>、TStack<T>、TDictionary<TKey, TValue>,还有针对于对象使用的TObjectList<T>等几个类。此外,还提供了TArray数组辅助静态类,封装了数组(array of T)的几个常用操作,如排序等。
但是在智能感知的时候,TList<T>等泛型集合提示好像有些BUG:
program TestTList;
2
3{$APPTYPE CONSOLE}
4
5uses
6 SysUtils,
7 Classes,
8 Generics.Collections; // 泛型集合命名空间,太优美了!
9
var
intList: TList<Integer>;
oldList: TList;
n, elem: Integer;
pTmp: Pointer;
begin
// 以下代码测试旧的集合对象
oldList := TList.Create;
oldList.Add(Pointer(1));
oldList.Add(Pointer(2));
oldList.Add(Pointer(3));
Writeln('TList start');
for n := 0 to oldList.Count - 1 do
begin
Writeln(Integer(oldList
));
end;
for pTmp in oldList do
begin
Writeln(Integer(pTmp));
end;
FreeAndNil(oldList);
// 以下代码测试整形泛型集合对象
intList := TList<Integer>.Create;
intList.Add(1);
intList.Add(2);
intList.Add(3);
Writeln( #13 + #10 + 'TList<T> start');
for n := 0 to intList.Count - 1 do
begin
Writeln(intList
);
end;
for elem in intList do
begin
Writeln(elem);
end;
FreeAndNil(intList);
// ----------------------------------------------------------
Writeln('press any key Readln;
end.
运行结果:
program TestTObjectList;
2
3{$APPTYPE CONSOLE}
4
5uses
6 SysUtils,
7 Contnrs,
8 Generics.Collections,
9 Felix in 'Felix.pas';
var
objList: TObjectList<TFelix>;
oldObjList: TObjectList;
n: Integer;
felix: TFelix;
pFelix: Pointer;
begin
// 以下代码测试旧对象集合
Writeln('TObjectList start');
oldObjList := TObjectList.Create; // 1*
for n := 0 to 2 do
begin
oldObjList.Add(TFelix.Create);
end;
for pFelix in oldObjList do
begin
Writeln(TFelix(pFelix).Id);
end;
FreeAndNil(oldObjList);
// 以下代码测试泛型对象集合
Writeln(#13 + #10 + 'TObjectList<T> start');
objList := TObjectList<TFelix>.Create; // 2*
for n := 0 to 2 do
begin
objList.Add(TFelix.Create);
end;
for felix in objList do
begin
Writeln(felix.Id);
end;
FreeAndNil(objList);
// ----------------------------------------------------------
Writeln('press any key Readln;
end.
![](http://images.cnblogs.com/cnblogs_com/felixyeou/Delphi/%E4%BD%93%E9%AA%8C%E6%B3%9B%E5%9E%8B/p3.gif)
图3
如果我们将代码中的第1*处修改成:
oldObjList := TObjectList.Create(False);
将产生如下结果:
![](http://images.cnblogs.com/cnblogs_com/felixyeou/Delphi/%E4%BD%93%E9%AA%8C%E6%B3%9B%E5%9E%8B/p4.gif)
图4
相对于TObjectList<T>,没有Create(AOwnsObjects: Boolean)方式的重载,我们如何才能让TObjectList<T>“不拥有”对象,当TObjectList<T>中的元素重新赋值、TObjectList<T>集合对象销毁的时候,怎样能保证里面的旧元素不进行销毁操作呢?答案是:不能。
四:TList<T>和TObjectList<T>的区别
如果将上面代码的objList对象声明时改成TList<TFelix>类型,并将第2*处代码改成objList := TList<TFelix>.Create;结果就和使用TObjectList(图4)的效果一样了,当调用方法SetItem或者集合被销毁后,旧元素或者内部的元素不会被销毁。原因在于,TObjectList<T>从TList<T>继承而来,只重写了Notify方法,此方法在集合内元素改变(指针变换、删除、添加)等操作时调用。
请阅读Generics.Collections.pas文件第1236行,TObjectList<T>重写了Notify方法后,先调用了超类的Notify方法,然后判断操作如果为cnRemoved则将元素.Free,所以元素在此处被析构。
五:后记
使用TObjectList<T>会将对象自动销毁,使用TList<T>不会将对象自动销毁。受Symbian编程的影响,我习惯于对象自己创建、对象自己销毁,特别是在使用对象集合类,有时候一个对象可能在这个集合内,同时又在另外一个集合内。如果TObjectList<T>把对象销毁了,在另外一个集合内使用对象会造成不可预料的后果,所以建议大家不要使用TObjectList<T>。
其他几个泛型类TDictionary<>等,方法和代码都和.net的类似,看了看代码,真是让人遐想连篇,此处不再介绍。
相关文章推荐
- (原创)Delphi2009初体验 - 语言篇 - 体验泛型(二)
- Delphi2009初体验 - 语言篇 - 体验泛型(一)
- Delphi2009初体验 - 语言篇 - 体验泛型(二)
- (原创)Delphi2009初体验 - 语言篇 - 智能指针(Smart Pointer)的实现
- (原创)Delphi2009初体验 - 语言篇 - 反射单元ObjAuto的加强
- (改进)Delphi2009初体验 - 语言篇 - 智能指针(Smart Pointer)的实现(二)
- Delphi2009初体验 - 语言篇 - 智能指针(Smart Pointer)的实现
- (原创)Delphi2009初体验 - IDE篇 - D2009 VS VS2005
- Delphi2009初体验 - 语言篇 - 反射单元ObjAuto的加强
- (转)Delphi2009初体验 - 语言篇 - 智能指针(Smart Pointer)的实现
- 五、Delphi 2009 泛型容器单元(Generics.Collections): TDictionary<T>
- Delphi 2009 中的泛型
- [导入]Delphi 2009 泛型容器单元(Generics.Collections)[1]: TList
- 淺談怎么样运用Delphi 2009地泛型容器類別
- Delphi 2009 泛型容器单元(Generics.Collections)[4]: TDictionary<T>
- 淺談怎么样运用Delphi 2009地泛型容器類別
- 一、Delphi 2009 中的泛型
- 六、Delphi 2009 泛型容器单元(Generics.Collections)[5]: TObject...<T> 系列
- Delphi 2009 泛型容器单元(Generics.Collections)[2]: TQueue<T>
- 淺談如何使用Delphi 2009的泛型容器類別