delphi – 编写记录的通用TList

delphi – 编写记录的通用TList,第1张

概述我正在尝试编写包含特定类型记录通用TList.从大卫在这 question的回答开始,我写了这堂课: Type TMERecordList<T> = Class(TList<T>) Public Type P = ^T; Private Function GetItem(Index: Integer): P; Public Procedure Assign 我正在尝试编写包含特定类型记录的通用TList.从大卫在这 question的回答开始,我写了这堂课:

Type  TMERecordList<T> = Class(TList<T>)  Public Type    P = ^T;  Private    Function GetItem(Index: Integer): P;  Public    Procedure Assign(Source: TMERecordList<T>); Virtual;    Function First: P; Inline;    Function Last: P; Inline;    Property Items[Index: Integer]: P Read GetItem;  End;Procedure TMERecordList<T>.Assign(Source: TMERecordList<T>);Var  SrcItem: T;Begin  Clear;  For SrcItem In Source Do    Add(SrcItem);End;Function TMERecordList<T>.First: P;Begin  Result := Items[0];End;Function TMERecordList<T>.GetItem(Index: Integer): P;Begin  If (Index < 0) Or (Index >= Count) Then    Raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);  Result := @List[Index];End;Function TMERecordList<T>.Last: P;Begin  Result := Items[Count - 1];End;

使用返回指向记录的指针的方法效果很好(不完美),因为指针可以像大多数用例中的记录一样使用.使用包含属性和setter的记录,这些测试用例按预期工作:

TMETestRecord = Record  Private    FID:     Word;    FText:   String;    FValues: TIntegers;    Procedure SetID(Const Value: Word);    Procedure SetText(Const Value: String);    Procedure SetValues(Const Value: TIntegers);  Public    Property ID: Word Read FID Write SetID;    Property Text: String Read FText Write SetText;    Property Values: TIntegers Read FValues Write SetValues;  End;  // TestSetItem1  rl2[0] := rl1[0];  // TestSetItem2  r.ID     := 9;  r.Text   := 'XXXX';  r.Values := [9,99,999,9999];  rl1[0]   := r;  // TestAssignEmpty (rl0 is empty... after assign so should rl2)  rl2.Assign(rl0);  // TestAssignDeepcopIEs (modifications after assign should not affect both records)  rl2.Assign(rl1);  r.ID     := 9;  r.Text   := 'XXXX';  r.Values := [9,9999];  rl1[0]   := r;

问题1 – 修改包含的记录

…此测试用例编译并运行但不能按预期工作:

// TestSetItemFIElds  rl1[0].ID     := 9;  rl1[0].Text   := 'XXXX';  rl1[0].Values := [9,9999];

修改应用于记录的临时副本,而不是应用于列表中存储的副本.我知道这是一个已知的和预期的行为,如其他问题所述.

但是……有没有办法呢?我在想,如果TMERecordList<> .Items属性有一个setter,编译器可能会执行实际需要的 *** 作.可以吗?我知道大卫有一个解决方案,正如question所暗示的……但我似乎无法自己找到它.

这真的很不错,因为它允许我有一种方法使用与TList对象相同(或几乎)的列表.拥有相同的界面意味着我可以在需要时轻松地从对象更改为记录,反之亦然.

问题2 – 界面歧义

拥有TList<>返回一个记录指针确实会造成一些界面模糊问题.一些TList<>方法接受T参数,我们知道作为记录,这些将通过值传递.那么这些方法应该怎么做呢?我应该重新考虑一下吗?我正在特别谈论这些方法:

> Remove和RemoveItem
> Extract和ExtractItem
>包含IndexOf,IndexOfItem和LastIndexOf

关于如何测试包含的项目以查看它们是否与参数记录值匹配,存在一些模糊性.该列表很可能包含相同的记录,这可能成为用户代码中的错误来源.

我试图不从TList<>中获取它,以便没有这些方法,但它是一团糟.我不能写一个类似于TList的类而不写自己的TListHelper.不幸的是,System.Generics.Collections的一个必需的字段是私有的,如FCount,并且不能在单元外使用.

解决方法 问题1

您的Items属性未标记为默认值.因此,您的错误代码正在获取基类默认属性.将default关键字添加到Items属性:

property Items[Index: Integer]: P read GetItem; default;

问题2

这实际上是源自TList< T>的结果.我不建议这样做.封装TList< T>的实例.因此明确定义接口而不是继承它.或者直接在代码中实现列表功能.毕竟,它只不过是一个动态数组的包装器.

对于我的课程的价值,不要使用TList< T>毕竟,当Emba在最近的一个版本中打破了这个课程时,我很满意这个决定.

总结

以上是内存溢出为你收集整理的delphi – 编写记录的通用TList全部内容,希望文章能够帮你解决delphi – 编写记录的通用TList所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1273448.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-08
下一篇 2022-06-08

发表评论

登录后才能评论

评论列表(0条)

保存