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框架,可惜还是个半吊子.然后遇到了一个困扰了一整天的问题.一直调试都 ...
随机推荐
- JavaWeb——java.lang.UnsatisfiedLinkError
java.lang.UnsatisfiedLinkError: Native Library sqlite-3.8.6-amd64-sqlitejdbc.dll already loaded in a ...
- Variables多种表达
Variables:TF基础数据之一,常用于变量的训练...重要性刚学TF就知道了 1.tf.Variable() tf.Variable(initial_value=None, trainable= ...
- hadoop 二次排序的思考
name sorce jx 10 gj 15 jx 20 gj 30 1. 二次排序 key如何定义 2. grouping 是不是一定要实现,不实现可以吗? 3. 二次排序的本质是什么 4. 如果以 ...
- vue 全局组件【原】
1.目录 2.内容 -Loading.vue <template> <div class="loading"> loading... </div> ...
- Python常用内置函数介绍
Python提供了一个内联模块buildin.内联模块定义了一些开发中经常使用的函数,利用这些函数可以实现数据类型的转换.数据的计算.序列的处理等功能.下面将介绍内联模块中的常用函数. Python内 ...
- install oracle 12c on redhat
---恢复内容开始--- 1. 确定VM的硬盘空间是否够 df- h, 硬盘空间free disk 15G 比较稳妥 2. 确定好网络,需要remote connect ifconfig 3. ...
- springcloud-知识点总结(二):Ribbon&Feign
1.Ribbon简介 前面讲了eureka服务注册与发现,但是结合eureka集群的服务调用没讲. 这里的话 就要用到Ribbon,结合eureka,来实现服务的调用: Ribbon是Netflix发 ...
- oracle函数nvl, nvl2, nullif
nvl函数 语法: NVL(表达式1, 表达式2) select nvl(s.name, '未填写') from student s 如果表达式1的值为空, 则显示第二个值, 否则显示原来的值, nv ...
- sh 了解
shell 脚本中 `dirname $0` 在命令行状态下单纯的执行时没有意义的,因为他返回当前路径的“.”. 在脚本中他返回这个脚本文件放置的目录,并可以根据这个目录来定位所要运行的程序的相对位置 ...
- 20175314 《Java程序设计》第六周学习总结
20175314 <Java程序设计>第六周学习总结 教材学习内容总结 第七章:内部类与异常类 内部类:内部类就是在一个类中再定义一个类,这个在类中定义的类就叫做内部类,而包含内部类的类叫 ...