- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
Delphi 有一个为泛型类重复代码的坏习惯。即使代码确实相同,因为泛型类型是相似的。
我想防止重复存储不同的类。
在我的通用容器中,我仅在需要时使用 Free
进行清理。
假设我有一个像这样的通用容器:
unit Unit1;
interface
uses Generics.Collections;
type
TMyContainer<T> = class(TObject)
strict private
FData: TList<T>;
public
constructor Create; virtual;
end;
我知道T
通常是一个对象。因为所有对象实际上都是 TObject
我不希望我的容器为不同类型的对象创建重复的通用代码。
下面的技巧可以防止重复吗?
A- 用类函数替换构造函数:
unit Unit2;
uses Unit1;
type
TMyContainer<T> = class(Unit1.TMyContainer<T>)
public
class function Create: TMyContainer<T>; static;
end;
B:实现类函数Create
,如下所示:
class function TMyContainer<T>.Create: TMyContainer<T>;
var
X: TObject;
begin
if GetTypeKind(T) = tkClass then begin
X:= Unit1.TMyContainer<TObject>.Create;
end else begin
X:= Unit1.TMyContainer<T>.Create;
end;
TObject(Result):= X;
end;
这个技巧是否可以防止编译器为不同类型的对象生成重复的代码,或者是否会因为我使用了不正确的假设而失败?
请注意,我不想使用非通用存储来存储我的数据。
完整示例代码如下
unit Unit49;
interface
uses Generics.Collections;
type
TMyContainer<T> = class(TObject)
strict private
FData: TList<T>;
public
constructor Create; virtual;
end;
implementation
constructor TMyContainer<T>.Create;
begin
inherited Create;
FData:= TList<T>.Create;
end;
end.
示例程序
program Project85;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
Unit49 in 'Unit49.pas';
type
TMyContainer<T> = class(Unit49.TMyContainer<T>)
public
class function Create: TMyContainer<T>; static;
end;
{ TMyContainer<T> }
class function TMyContainer<T>.Create: TMyContainer<T>;
var
Y: T;
X: TObject;
begin
if GetTypeKind(T) = tkClass then begin
X:= Unit49.TMyContainer<TObject>.Create;
end else begin
X:= Unit49.TMyContainer<T>.Create;
end;
TObject(Result):= X;
end;
var
A: TMyContainer<TObject>;
B: TMyContainer<TLanguages>;
begin
A:= TMyContainer<TObject>.Create;
B:= TMyContainer<TLanguages>.Create;
readln;
end.
最佳答案
Will this trick work to prevent the compiler from generating duplicate code for different types of objects, or will this fail because I'm using incorrect assumptions?
不,这不会起作用。
基本上,编译器遵循您的 T
遍历整个类层次结构并将其替换为特定类型。
首先,您将拥有单独的 TList<T>
为 TObject
生成代码和TLanguages
因为你的容器被声明为 FData: TList<T>
, 然后你的技巧集合也继承自通用 T
TMyContainer<T> = class(Unit49.TMyContainer<T>)
并且类函数中的整个代码基本上是无用的。
编译器将为 Unit49.TMyContainer<TLanguages>
生成重复代码类以及 Unit49.TMyContainer<TObject>
类。
从您的示例中很难说出您想要避免哪些代码重复。如果容器类像您在示例中编写的那样简单,那么所有代码重复都将来自 TList<T>
类(class)。如果您想避免这种情况,则没有简单的出路。
您的问题的部分原因在于您有 T
那可以是任何东西。很难对其进行优化。您可以获得的最大优化是使用 array of T
用于存储数据,然后委派操作函数,您可以在其中使用 TObject
作为所有类和普通类的基础 T
为他人。
您能从上面获得多少 yield 还取决于您使用哪个Delphi版本,因为在最新版本中TList<T>
已使用类似技术进行了一些优化。
但是,如果您可以为类和其他类型拥有单独的容器,那么您可以实现 TObject
的代码折叠和后代容器使用 TObjectList<TObject>
(或者甚至是 Windows 上的非泛型 TObjectList
)用于存储所有特定类并通过类型转换实现您需要的任何类型安全函数的瘦包装函数。当然,每个这样的函数都会为每种特定类型生成一些代码,但由于它们只是类型转换包装器,因此代码量不会像使用完整的 TList<T>
那样多。对于每个类类型。
TMyObjectContainer<T> = class(TObject)
strict private
FData: TObjectList<TObject>;
public
constructor Create; virtual;
destructor Destroy; override;
function Data(index: integer): T;
end;
constructor TMyObjectContainer<T>.Create;
begin
inherited;
FData := TObjectList<TObject>.Create;
end;
constructor TMyObjectContainer<T>.Create;
begin
FData.Free;
inherited;
end;
function TMyObjectContainer<T>.Data(index: integer): T;
begin
Result := T(FData.Items[index]);
end;
关于delphi - 如何防止为泛型类生成重复的代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37364611/
我是一名优秀的程序员,十分优秀!