前端开发入门到精通的在线学习网站

网站首页 > 资源文章 正文

Delphi基础教程图文版之泛型容器

qiguaw 2025-03-04 13:40:42 资源文章 14 ℃ 0 评论

官方描述

Unit that implements generic container classes to group data items in arrays, dictionaries, lists, stacks, queues, and more.

译文:实现泛型容器类的单元,以在数组中对数据项进行分组,词典,列表,堆栈,队列等。

起初在接触到Delphi的时候我以为没有这一部分内容,所有的都要自己实现,此处请原谅我的无知。。。。

关于从那个版本开始支持泛型的,我在官方文档上没有找到对应的说明,也可能是我英语太菜,在官网迷路了。

根据百度得来的结果2007的版本没有(真百度的)支持2009的版本(万一老师的博客上引用的也是这个版本)开始出现,也就是最早支持泛型容器的版本应该是Delphi2009

聊泛型容器避不开的就是泛型的概念,之前看哔哩哔哩的网友留言从泛型一节就是开始懵逼了。其实大可不必,泛型可以理解为一个变量,它的值是一个具体的类型

嗯,其实也可以把它当作孙大圣,它可以变成任何东西

Collections单元

在这个单元内一共定义了13个容器类,我们在其中甚至可以看到线程队列。那么问题来了,我们需要精通或者学习所有的类吗?答案是否定的

容器类就我个人的理解其实一共有两大表现形式,一种是列表形式的像数组,而另一种形式则以 Key,Value 成对的形式。也就是说我们从中选择两个比较有代表性的类进行学习即可。下面是我选择的两个类

  • System.Generics.Collections.TList:很明显这个是列表
  • System.Generics.Collections.TDictionary:Dictionary这个单词翻译成中文是字典的意思,不知道为啥这么起名,它是K,V形式的代表

注意:在单元内我们还可以看到相似的类例如
System.Generics.Collections.TObjectList

System.Generics.Collections.TList
区别在于带有Object的类会在删除元素时释放对象,而没有带Object的不会释放

API代码

针对容器类学习的总原则是围绕增、删、改、查这几个核心的API功能即可,其他的就只能现用现查了,不知道别人写代码是什么习惯,我写代码的时候帮助文档基本上都是开着的。。。

下面是针对两个容器类的代码实现

TList

实体类(TStudent)代码

type

    TStudent = class
    private
        FName: string;
    public
        property Name: string read FName write FName;
        // 构造方法
        constructor Create; overload;
        // 有参构造方法
        constructor Create(FName: string); overload;
    end;

constructor TStudent.Create;
begin

end;

constructor TStudent.Create(FName: string);
begin
    Self.FName := FName;
end;

操作类(即增、删、改、查),我没有使用内联,几次想用都删了

uses
    System.Generics.Collections, System.SysUtils;

var
    // 文档上的定义是TList,而我们的定义尖括号中的是TStudent,这就是泛型的用法
    StudentList: TList;
    // 循环中使用获取TList成员
    Stu: TStudent;

begin
    // 初始化学生列表
    StudentList := TList.Create;
    StudentList.add(TStudent.Create('小强'));
    StudentList.add(TStudent.Create('萧蔷'));
    StudentList.add(TStudent.Create('小黑'));
    StudentList.add(TStudent.Create('小白'));
    StudentList.add(TStudent.Create('小黄'));

    // 开始之前输出一次
    for Stu in StudentList do begin

        Writeln('学生信息是:' + Stu.Name);
    end;

    // 泛型容器自带的删除函数,偷个懒
    StudentList.Delete(0);

    // 修改,查询到指定的学生,修改其值即可
    StudentList.Items[0].Name := '小白';


    // 查询,其实和数组的操作没有太大区别
    for Stu in StudentList do begin

        Writeln('学生信息是:' + Stu.Name);
    end;

end.

TDictionary

此类容器的特点是 key 唯一,并且几乎所有的操作都是根据 key 来的

改造下实体类(TStudent)增加一个属性,代码如下

type

    TStudent = class
    private
        FName: string;
        FId: string;
    public
        property Name: string read FName write FName;
        property Id: string read FId write FId;

        // 构造方法
        constructor Create; overload;
        // 有参构造方法
        constructor Create(FName: string; FId: string); overload;
    end;

constructor TStudent.Create;
begin

end;

constructor TStudent.Create(FName: string; FId: string);
begin
    Self.FName := FName;
end;

操作类(即增、删、改、查)


{注意单元的引用}
uses
    System.Generics.Collections, System.SysUtils;

var
    // 文档上的定义是TList,而我们的定义尖括号中的是TStudent,这就是泛型的用法
    StudentMap: TDictionary;
    // 循环中使用获取TList成员
    Key: string;
    Student,Stu: TStudent;

begin
    // 初始化学生列表
    StudentMap := TDictionary.Create;
    // 此处的添加其实并不是太好,根据文档描述,当我们添加的元素的key已经存在会抛出异常
    // 建议使用AddOrSetValue
    StudentMap.add('1001', TStudent.Create('1002', '小强'));
    StudentMap.add('1002', TStudent.Create('1001', '萧蔷'));
    StudentMap.add('1003', TStudent.Create('1003', '小黑'));
    StudentMap.add('1004', TStudent.Create('1004', '小白'));
    StudentMap.add('1005', TStudent.Create('1004', '小黄'));

    // 注意此处获取是key,也就是1001 1002这些东西
    for Key in StudentMap.Keys do begin

        // 获取到key之后,再根据key获取对应value也就是学生对象
        // 这里的获取方式有点儿任性居然要的是一个指针,而不是直接返回
        StudentMap.TryGetValue(Key, Student);
        // 最好判断一下,否则容易出现空指针
        if (Student <> nil) then
            Writeln('学生信息是:' + Student.Name)
    end;

    // 删除元素,无论什么操作都是通过key去操作,因为key是不可以重复的
    StudentMap.Remove('1005');

    // 修改,没有就添加,有就更新
    StudentMap.AddOrSetValue('1004', TStudent.Create('1004', '小黄'));

    // 直接获取value
    for Stu in StudentMap.values do begin
        // 最好判断一下,否则容易出现空指针
        if (Stu <> nil) then
            Writeln('学生信息是:' + Student.Name)

    end;
end.

参考资料

万一的博客:
https://www.cnblogs.com/del/category/113556.html

官方文档:
http://docwiki.embarcadero.com/Libraries/Sydney/en/System.Generics.Collections

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表