对 Variant 变量使用 ToString

Fab*_*zio 3 delphi tostring variant delphi-xe7

以下代码产生EVariantInvalidOpError异常:

var
  i : Variant;
begin
  i := 10;
  ShowMessage(i.ToString());
end;
Run Code Online (Sandbox Code Playgroud)

显示“无效变量操作”异常对话框的图片

以下所有内容都很好,但我不明白为什么该ToString函数会引发类型变量的异常Variant

var
  i : Variant;
begin
  i := 10;
  ShowMessage(VarToStr(i));
end;

var
  i : Integer;
begin
  i := 10;
  ShowMessage(i.ToString());
end;
Run Code Online (Sandbox Code Playgroud)

Pet*_*olf 5

变体允许您在其中存储各种类型的值,而类型在编译时可能是未知的。您可以将整数值写入Variant类型的单个变量,然后用字符串值覆盖它。除了值变体记录之外,还存储类型信息。在这些值中,其中一些是自动分配和/或引用计数的。当从变量写入或读取值时,编译器在幕后做了很多事情Variant

类型的变体会varDispatch得到编译器的更特殊对待。varDispatch表示该值属于类型IDispatch(通常但不一定与 Windows COM 技术相关)。的实例通过和方法IDispatch提供有关其方法和属性的信息。您可以使用它的方法按名称查询信息。GetTypeInfoCountGetTypeInfoGetIDsOfNames

让我们先回答您评论中的问题:

为什么 Delphi 允许我使用该ToString函数,即使没有帮助器为该Variant类型实现此类函数?

这就是 Delphi 实现“后期绑定”概念的方式。它允许您调用编译时类型未知的对象的方法。其工作的先决条件是底层变体类型支持后期绑定。Delphi 内置了对varDispatch和变体的后期绑定的支持,如单元中的varUnknown过程所示。DispInvokeCoreSystem.Variants

我不明白为什么该ToString函数会引发类型变量的异常Variant

如上所述,在运行时,您的程序尝试调用ToString变体值的方法,在您的情况下,变体值的类型为varByte。由于它不支持后期绑定(以及进一步的序数变体类型),因此您会遇到异常。

要将变量值转换为字符串,请使用VarToStr.

以下是使用 Microsoft Speech API 进行后期绑定的简单示例:

uses
  Winapi.ActiveX,
  System.Win.ComObj;

var
  Voice: Variant;
begin
  CoInitialize(nil);
  try
    Voice := CreateOleObject('SAPI.SpVoice');
    Voice.Speak('Hello, World!');
  finally
    CoUninitialize;
  end;
end.
Run Code Online (Sandbox Code Playgroud)