我学Delphi心得及笔记----Variant 数据类型--无类型(第八讲)

为了完全支持OLE,32位Delphi 增加了Variant 数据类型,本节将从宏观角度来分析这种数据类型。实际上,Variant类型对Pascal语言有普遍而深入的影响,Delphi 控件库中与OLE 无关的地方也使用到这种类型。

Variant变量没有类型

一般说来,你可以用Variant 变量存储任何数据类型,对它执行各种操作和类型转换。需要注意的是:这违反了Pascal 语言的一贯原则,有悖于良好的编程习惯。variant 变量的类型检查和计算在运行期间才进行,编译器不会提示代码中的潜在错误,这些错误在进一步测试中才能发现。总之,你可以认为包含variant变量的代码是解释性代码,正如解释性代码一样,许多操作直到执行时才能知道,这对代码运行速度会有很大的影响。

上面对Variant 类型的使用提出了警告,现在来看看Variant 类型究竟能干什么。基本上说,如果声明了一个variant 变量:

procedure TForm1.Button1Click(Sender: TObject);
var
  j:Variant;
  i:Integer;
begin
  j:=4;
  i:=20;
  showmessage(IntToStr(j+i));
end;

执行代码如下图:

程序输出的结果是24,它把这两个数进行计算。

再看如下例子:

procedure TForm1.Button1Click(Sender: TObject);
var
  j:Variant;
  i:String;
begin
  j:='测试Variant';
  i:='这是个';
  showmessage(i+j);
end;

Variant类型可以根据操作自动判断数据类型,但这种类型还是少用,它会包含一些不易查觉的异常;

Variant类型内部结构

Delphi中定义了一个 variant 记录类型,TVarData,它与Variant 类型有相同的内存布局。你可以通过TVarData访问variant变量的实际类型。TVarData 结构中包含了Variant类型信息(由Vtype域表示)、一些保留域及当前值。

VType域的取值包括OLE 自动化中的所有数据类型,这些类型通常叫OLE 类型或variant 类型。以下是variant 类型的完整列表,按字母顺序排列:

  • varArray
  • varBoolean
  • varByRef
  • varCurrency
  • varDate
  • varDispatch
  • varDouble
  • varEmpty
  • varError
  • varInteger
  • varNull
  • varOleStr
  • varSingle
  • varSmallint
  • varString
  • varTypeMask
  • varUnknown
  • varVariant

你可以在Delphi 帮助系统的variants 主题下找到这些类型的说明。

还有许多操作variant 变量的函数,你可以用它们进行特定的类型转换,或通过它们获取variant变量的类型信息(例如VarType 函数),当你用variant变量写表达式时,Delphi会自动调用这些类型转换和赋值函数。另外还有操作variant 数组的例程,你可以通过帮助文件的Variant support routines 主题了解相关内容。

Variant类型运行很慢!

Variant 类型代码运行很慢,不仅数据类型转换如此,两个值为整数的Variant 变量相加也是如此。它们几乎跟Visual Basic这种解释性代码一样慢!为了比较Variant变量和整型变量的运行速度,请看例VSpeed 。

程序中设置了一个循环,记录运行时间并在进程条中显示运行状态。下面是基于variant类型的一段代码,基于整型的代码与此相似:

procedure TForm1.Button1Click(Sender: TObject);
var
  time1, time2: TDateTime;
  n1, n2: Variant;
begin
  time1 := Now;
  n1 := 0;
  n2 := 0;
  ProgressBar1.Position := 0;
  while n1 < 5000000 do
  begin
    n2 := n2 + n1;
    Inc (n1);
    if (n1 mod 50000) = 0 then
    begin
      ProgressBar1.Position := n1 div 50000;
      Application.ProcessMessages;
    end;
  end;
  // we must use the result
  Total := n2;
  time2 := Now;
  Label1.Caption := FormatDateTime (
    'n:ss', Time2-Time1) + ' seconds';
end;

记时这段代码值得一看,因为你可以把它用到任何类型的性能测试中。正如你所看到的,程序用Now 函数获取当前的时间,用FormatDateTime 函数格式化时间差,输出结果以分("n")和秒("ss")表示。除此之外,你可以用Windows API的GetTickCount 函数,该函数能精确显示操作系统启动后至当前的毫秒数。

从上例可见两者的速度差异非常之大,以至于不用精确记时也能看到这种差异。图10.2是在本人计算机上运行程序看到的结果。当然运行结果取决于运行程序的计算机,但是两者的数值比不会有太大变化。

注意Variant类型能不用的时候就不要用,

posted @ 2011-07-10 18:23  Sam.山子  阅读(12537)  评论(0编辑  收藏  举报