The current state of generics in Delphi( 转载)
The current state of generics in Delphi
To avoid duplication of generated code, the compiler builders of Embarcadero have done a nice job. They introduced new instrinsics like IsManagedType
, GetTypeKind
and IsConstantType
(see this Stackoverflow answer), so they could make a function like the following generate a call to the exact function for the parametric type directly. This means that the code below "runs" completely inside the compiler, even the code in the called InternalAddMRef
and similar dispatching routines.
function TList.Add(const Value: T): Integer;
begin
if IsManagedType(T) then
begin
if (SizeOf(T) = SizeOf(Pointer)) and (GetTypeKind(T) <> tkRecord) then
Result := FListHelper.InternalAddMRef(Value, GetTypeKind(T))
else if GetTypeKind(T) = TTypeKind.tkVariant then
Result := FListHelper.InternalAddVariant(Value)
else
Result := FListHelper.InternalAddManaged(Value);
end else
case SizeOf(T) of
1: Result := FListHelper.InternalAdd1(Value);
2: Result := FListHelper.InternalAdd2(Value);
4: Result := FListHelper.InternalAdd4(Value);
8: Result := FListHelper.InternalAdd8(Value);
else
Result := FListHelper.InternalAddN(Value);
end;
end;
That, in its turn, means that if you code something like:
var
List: TList<string>;
begin
List := TList<string>>.Create;
List.Add('Hello');
then
List.Add('Hello');
is in fact directly compiled as
List.FListHelper.DoAddString('Hello');
i.e. TList.Add
does not have any runtime code at all, the result of "calling" it (see above) is the generation of a direct call to the DoAddString
function. That is a simple method, not generic, not virtual or dynamic, like all the other methods of TListHelper, so the unused functions can be eliminated by the linker. This also means there is hardly any duplication of generated code anymore, i.e. if another part of the same executable also uses TList<string>.Add
it will use the same function.
No code duplication?
Well, this means that if the class is coded like above, there is no unnecessary duplication of generated code anymore. That is cool and can probably reduce the expected bloat caused by using generics.
But it also means that it greatly reduces one of the advantages associated with generics: no unnecessary duplication of source code. You write a routine once, and only the type it works on is parametrized. The compiler takes care of generating code for each used routine and parametric type.
But then you still get the dreaded bloat. So you either duplicate a lot of source code (take a look at the code of TListHelper
in System.Generics.Collections
to see what I mean; for example, the functions DoAddWideString
, DoAddDynArray
, DoAddInterface
and DoAddString
contain exactly the same code, except for the lines where FItems^
is cast each to a different pointer type), which is almost as much work as writing a separate TList
for each type, or you use the naïve approach, writing code only once, as generics should actually be used. But then you could get bloat again, i.e. it is well possible that the same routine gets generated multiple times, in different units of the same executable.
What to do?
There is not much we can do, except to emphatically ask Embarcadero to put the kind of logic that was implemented in TList<T>
and other generic classes to avoid duplication of generated code, in the compiler and linker, so we don't have to write huge helper classes nor get the bloat.
In the meantime, you can do what Embarcadero did: if your class is used a lot for many different types, do a lot of "copy and paste generics". Otherwise, if you only have to deal with a few types and in a few places, simply use the naïve approach. Or you use a hybrid approach, using the intrinsics mentioned above and implementing the most used helper functions for the types you need most.
Let's hope they get a lot of requests and implement these things in the compiler and linker, like other languages with generics, e.g. C# or C++, do.
Rudy Velthuis
The current state of generics in Delphi( 转载)的更多相关文章
- “Operation is not valid due to the current state of the object.”
将Repeater单页显示的2000条数据一次性提交的时候出现这个错误: Operation is not valid due to the current state of the object. ...
- 关于 error: Operation is not valid due to the current state of the object。
今天碰到一个特别的异常. Operation is not valid due to the current state of the object. at System.Web.HttpValueC ...
- Error occurred in deployment step 'Add Solution': Operation is not valid due to the current state of the object.
Sharepoint 部署的时候出现一个错误 Error occurred in deployment step 'Add Solution': Operation is not valid due ...
- Operation is not valid due to the current state of the object.
今天遇到一个asp.net的草郁闷的问题,看下截图 狂晕啊,在google上狂搜了一下,好在已经有大侠也遇到过这个问题了,先看下别人的解决办法吧 Operation is not valid due ...
- Unable to boot device in current state: Creating
安装完xcode6.1后,将其改名为Xcode6.1.app,再移动个位置,启动模拟器,问题来了: Unable to boot device in current state: Creating 解 ...
- Cannot attach medium 'D:\program\VirtualBox\VBoxGuestAdditions.iso' {}: medium is already associated with the current state of machine uuid {}返回 代码: VBOX_E_OBJECT_IN_USE (0x80BB000C)
详细的错误信息如下: Cannot attach medium 'D:\program\VirtualBox\VBoxGuestAdditions.iso' {83b35b10-8fa2-4b81-8 ...
- vs问题解决:an operation is not legal in the current state
debug时弹出提示框:内容有:an operation is not legal in the current state 解决方案: Go to Tools > Options > D ...
- GridView Postback后出错Operation is not valid due to the current state of the object.
一.问题起因 最近项目中有一页面第一次search后正常,但是再次点击其它任何按钮都会报错,亦即postback后页面有问题,经检查是由于页面有一GridView且数据量极大,记录大概有上千条,这儿解 ...
- 前端 vue单页面应用刷新网页后vuex的state数据丢失的解决方案(转载)
最近接手了一个项目,前端后端都要做,之前一直在做服务端的语言.框架和环境,前端啥都不会啊. 突然需要前端编程,两天速成了JS和VUE框架,可惜还是个半吊子.然后遇到了一个困扰了一整天的问题.一直调试都 ...
随机推荐
- java基础-反射(细节)
java面试题--java反射机制? Java反射机制的作用:1)在运行时判断任意一个对象所属的类.2)在运行时判断任意一个类所具有的成员变量和方法.3)在运行时任意调用一个对象的方法4)在运行时构造 ...
- 验证Textbox的字符长度
private void textBox1_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e) { ) { //Indi ...
- BZOJ 1257: [CQOI2007]余数之和
1257: [CQOI2007]余数之和 Time Limit: 5 Sec Memory Limit: 128 MB Description 给出正整数n和k,计算j(n, k)=k mod 1 ...
- 【学习】基础知识:数组和矢量计量【Numpy】
Numpy是高性能科学计算和数据分析的基础包.功能如下: ndarray 一个具有矢量算法运算和复杂广播能力的快速且节省空间的多维数组 用于对整组数据进行快速运算的标准数学函数(无需编写循环) 用于读 ...
- Swift get和set方法以及只读属性(计算型属性,本身不保存数据,都是通过计算获得结果)
import UIKit class Person: NSObject { private var _name: String? var name: String? { get { return _n ...
- tomcat 8 在线管理admin配置
在tomcat8下,更加注重安全性.如果要使用在管理控制台部署应用,需要修改更多的配置. 在$tomcat_base$/webapps/manager/META-INF/context.xml中 添加 ...
- [PAClient Error] Error: E4356 File does not exist armv7
[PAClient Error] Error: E4356 File does not exist: /Users/tt/PAServer/scratch-dir/Administrator-snIO ...
- Java 学习笔记提高篇
Java笔记(提高篇)整理 主要内容: 面向对象 异常 数组 常用类 集合 IO流 线程 反射 Socket编程 1. 面向对象 1.1包 用来管理Java中的类, 类似文件夹管理文件一样. 因 ...
- Pandas数据的去重,替换和离散化,异常值的检测
数据转换 移除重复数据 import pandas as pd import numpy as np from pandas import Series data = pd.DataFrame( {' ...
- 微服务SpringCloud无法进行服务消费
最近用SpringCloud做微服务,一直无法成功进行服务消费. 我使用的服务消费者是Feign,声明式调用服务提供者. 排查过程 1.检查服务提供者: (1)对提供的方法进行测试,确保提供的服务没有 ...