分享
 
 
 

Delphi.NET 内部实现分析(5)

王朝delphi·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

Delphi.NET 内部实现分析(5)

2.5 其它

在了解了Borland.Delphi.System中的几个重要部分之后,剩下的就是一些零零碎碎的扫尾工作。

2.5.1 类型别名

为兼容Delphi中的特有类型,Borland.Delphi.System单元中定义了很多类型别名。

如我们前面分析过的TObject就是System.Object的别名。

//-----------------------------------------Borland.Delphi.System.pas--

type

TDateTime = type Double;

Extended = type Double; // 80 bit reals are unique to the Intel x86 architecture

Comp = Int64 deprecated;

TGUID = packed record

D1: LongWord;

D2: Word;

D3: Word;

D4: array[0..7] of Byte;

end;

//-----------------------------------------Borland.Delphi.System.pas--

对于Delphi的TDateTime类型来说,它在实现上是以一个Double即8字节浮点数存储的,

兼容OLE自动化中的时间格式。在Delphi.NET中继承了这一存储方式,而没有直接使用BCL

提供的System.DateTime结构,不过仍然可以使用DateTime.FromOADate和

DateTime.ToOADate方法在System.DateTime和TDateTime之间双向转换。

格式存储说明如下(from MSDN)

OLE 自动化日期以浮点数形式实现,其值为距 1899 年 12 月 30 日午夜的天数。

例如,1899 年 12 月 31 日午夜表示为 1.0;1900 年 1 月 1 日早晨 6 点表示为 2.25;

1899 年 12 月 29 日午夜表示为 -1.0;1899 年 12 月 29 日早晨 6 点表示为 -1.25。

只有刻度值大于或等于正的或负的 31241376000000000 的 DateTime 对象才可以表示为

OLE 自动化日期。未初始化的 DateTime(即刻度值为 0 的实例)将转换为等效的未初始化

OLE 自动化日期(即值为 0.0 的日期,它表示 1899 年 12 月 30 日午夜)。

而Extended和Comp则只是一个简单的别名。TGUID也只是一个简单的重定义。

值得注意的是这里的packed关键字。在CLR中,类的成员的物理位置对程序本身是没有意义的,

CLR可以任意安排字段的位置以进行字节对齐等等优化操作。而为了与现有代码进行交互,CLR提供了

StructLayoutAttribute属性允许限定类型的内部物理结构。在Delphi.NET中可以通过packed

关键字定义此结构的成员必须按定义的次序在内存中排列,即LayoutKind.Sequential的形式。

而在Delphi.NET中,所有的record在实现上都是ValueType的子类,即值类型,直接在堆栈上操作。

2.5.2 异常

同TObject一样,Delphi中异常类继承链的根Exception在Delphi.NET中,也只是BCL的异常类

System.Exception的一个别名,而只是通过class helper提供源代码级兼容性。

//-----------------------------------------Borland.Delphi.System.pas--

Exception = System.Exception;

ExceptionHelper = class helper for Exception

private

class function CreateMsg(const Msg: string): Exception;

function GetHelpContext: Integer;

procedure SetHelpContext(AHelpContext: Integer);

public

// Doc: The help context return zero(0) if exception's helplink property

// cannot be parsed into an integer.

property HelpContext: Integer read GetHelpContext write SetHelpContext;

// constructor Create(const Msg: string) is provided by the CLR class

class function CreateFmt(const Msg: string; const Args: array of const): Exception;

class function CreateHelp(const Msg: string; AHelpContext: Integer): Exception;

class function CreateFmtHelp(const Msg: string; const Args: array of const;

AHelpContext: Integer): Exception;

end;

ExceptionClass = class of Exception;

EConvertError = class(Exception);

threadvar

_ExceptObject: TObject;

function ExceptObject: TObject;

//-----------------------------------------Borland.Delphi.System.pas--

几个类函数Create*(...)都只是对System.Exception构造函数的包装而已,

用于保存异常相关帮助文件路径的System.Exception.HelpLink属性,则被Delphi.NET

用于保存HelpContext,因为在VCL中,所有的异常都是共用一个帮助文件TApplication.HelpFile。

而ExceptObject函数则由编译器支持,提供访问当前被抛出的异常的手段。此函数在Delphi中

通过VCL维护的SEH异常链获取,而在Delphi.NET中只好由编译器在异常被截获后手动赋值给线程局部存储变量

_ExceptObject,然后再由ExceptObject函数读出,这只是语法一级兼容Delphi而已。

不过这个预览版好像没有提供threadvar的支持,只是把它简单的放到Borland.Delphi.System单元的

全局变量中,作为自动生成Unit类的一个静态成员变量而已,并非线程安全!在Borland.Delphi.Classes

中甚至直接把TThread的定义注释掉,实现不提供。估计还在开发中……sigh

2.5.3 断言(Assert)

断言负责在调试模式下检测一个条件是否成立,失败则引发异常。

//-----------------------------------------Borland.Delphi.System.pas--

interface

{ debugging functions }

procedure _Assert(const Message, Filename: AnsiString; LineNumber: Integer);

type

EAssertionFailed = class(Exception)

public

ShortMessage: string;

Filename: string;

LineNumber: Integer;

end;

resourcestring

SAssertionFailed = '%s (%s at %d)';

implementation

procedure _Assert(const Message, Filename: AnsiString; LineNumber: Integer);

var

LException: EAssertionFailed;

begin

{ TODO : Should we be using System.Diagnostics.Debug.Assert/Fail? }

{$MESSAGE WARN 'Assert doesn''t use CreateFmt because it returns the wrong type'}

LException := EAssertionFailed.Create(Format(SAssertionFailed, [Message, Filename, LineNumber]));

LException.ShortMessage := Message;

LException.Filename := Filename;

LException.LineNumber := LineNumber;

raise LException;

end;

//-----------------------------------------Borland.Delphi.System.pas--

_Assert函数的定义基本上是EAssertionFailed异常的一个简单包装。因为Delphi没有提供类似

C++中__FILE__、__LINE__之类的预定义宏,故而只能由编译器在用户使用到Assert函数时,

将当前文件名、行号等调试信息编译进代码中,即在编译器一级提供断言实现。

//-----------------------------------------Borland.Delphi.System.pas--

function Assigned(const AGCHandle: GCHandle): boolean;

begin

Result := AGCHandle.IsAllocated;

end;

//-----------------------------------------Borland.Delphi.System.pas--

//-----------------------------------------GCHandle.cs--

namespace System.Runtime.InteropServices {

public struct GCHandle {

private IntPtr m_handle;

public bool IsAllocated { get { return m_handle != IntPtr.Zero; } }

}

}

//-----------------------------------------GCHandle.cs--

Assigned则是对一个引用类型变量进行检测,与Delphi类似,Delphi.NET中直接通过检测引用类型值

是否为空(null)判断是否有效,但对于值类型则将之与0进行比较。

2.5.4 随机数

Delphi.NET中的随机数基本上是对BCL相关类的一个简单包装,而BCL的随机数算法与VCL一样弱智,

简单的功能还凑合,BCL的System.Security.Cryptography.RandomNumberGenerator相比之下

随机性就好得多,不过要付出速度上的代价。

//-----------------------------------------Borland.Delphi.System.pas--

interface

{ random functions }

var

RandSeed: LongInt = 0;

procedure Randomize;

function Random(const ARange: Integer): Integer; overload;

function Random: Extended; overload;

implementation

var

LastRandSeed: Integer = -1;

RandomEngine: System.Random;

procedure InitRandom;

begin

if LastRandSeed <> RandSeed then

begin

if RandSeed = 0 then

RandomEngine := System.Random.Create

else

RandomEngine := System.Random.Create(RandSeed);

LastRandSeed := RandSeed;

end;

end;

procedure Randomize;

begin

LastRandSeed := -1;

RandSeed := 0;

end;

function Random(const ARange: Integer): Integer;

begin

InitRandom;

Result := RandomEngine.Next(ARange);

end;

function Random: Extended;

begin

InitRandom;

Result := RandomEngine.NextDouble;

end;

//-----------------------------------------Borland.Delphi.System.pas—

Delphi.NET 内部实现分析(6)

不好意思,实在想不到有什么值得说的了,只好草草结束了

2.5.5 其它.其它

Borland.Delphi.System单元虽然比Delphi中的System单元小的多,

但其中也充斥着大量常用但是实现代码枯燥的函数。如

数字处理函数集

字符串处理函数集

命令行信息获取函数集(CmdLine/ParamCount/ParamStr)

格式化输出函数集(Format等)

文本文件(即Text类型,而File类型文件不提供支持)开/关/读/写等函数集

动态数组管理(System.Array类型的简单包装)

当前路径及目录操作函数集

集合类型(CLR中并无集合概念,Set实现上是字节数组的简单包装)

其它一些杂项函数

等等等等

这些零散代码基本上都是对BCL相应功能的简单包装,这里就不一一详述了。

2.5.6 小结

至此,对Delphi.NET中核心单元Borland.Delphi.System单元的介绍

就告一段落了。通过对此单元的分析,我们大致了解了Delphi.NET中对于Delphi

一些核心概念的实现或模仿思路,但不排除在正式版中实现有所改变。

题外话:

首先感谢大家的热心支持,这是督促我这个懒人写完文章(哪怕是草草结束)的最大动力,

也希望这篇文章能够对大家了解即将到来的Delphi.NET、迎接.NET时代有所帮助。

这个系列文章到这里估计也就暂时告一段落了,因为时间仓促、准备不足而且

笔者水平有限,只涉及到Delphi.NET在实现上与Delphi不同的部分内容,

与Delphi.NET的改变来说只是冰山一角而已。本来还想扩大一点分析面,

但考虑到Delphi.NET中RTL其它单元大多只是对原有Delphi代码的BCL封装移植

技术难度并不大,对Delphi熟悉的读者直接阅读源程序可能比看我的文章更容易一些。

因此在分析完涉及到一些底层只是的Borland.Delphi.System后就此打住,

虽然有些虎头蛇尾之嫌,但总免得背画蛇添足之骂名 :)

至于构建在Delphi.NET的RLT之上的应用层架构VCL和以后可能要支持的CLX,

我就没有太多精力写文章介绍了。因为就目前实现的VCL代码来看,只是将以前的VCL代码

managed化而已,实现上还是使用Windows那套传统API管理窗口,与BCL的

System.Windows.Forms.Form根本不搭界。这样一来在Delphi.NET中又多了一个选择

VCL or CLX or System.Windows.Forms.Form...sigh,是好是坏只能待时间评判。

文中如果有解释不够清楚的地方,大家可以跟贴提出。也欢迎来信

于我讨论Delphi.NET和CLR相关问题。 再次感谢大家的支持!:)

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有