• 我学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类型能不用的时候就不要用,

  • 相关阅读:
    docker 镜像相关
    docker相关网站
    docker初识 一
    loadrunner Windows资源指标
    Codeforces Round #368 (Div. 2) Brain's Photos
    CodeForce 589J Cleaner Robot
    CodeForce 677I Lottery
    CodeForce 677D Boulevard
    CodeForce 589B Layer Cake
    Map的遍历
  • 原文地址:https://www.cnblogs.com/youshan/p/2102455.html
Copyright © 2020-2023  润新知