如何判断Delphi变量是否为空字符串?

Nic*_*ges 8 delphi string delphi-xe variants

变种总是很有趣,是吗?

我正在研究D2007中最后一个将其迁移到Delphi XE的遗留应用程序.

在过渡期间,变体已经发生了很大的变化.

这行代码:

if (VarType(Value) = varString) and (Value = '') then 
  Exit;
Run Code Online (Sandbox Code Playgroud)

在D2007中返回True并退出,但在Delphi XE中没有.

我把它改成了这个:

if VarIsStr(Value) and (VarToStr(Value) = '') then
    Exit;
Run Code Online (Sandbox Code Playgroud)

我不相信这是"最好的"方式.Variants单元没有特定的调用来执行此操作,我当然记得这对于过去的人来说是一个问题.但是,搜索显示没有库函数或任何其他可接受的方式.

有"正确"或更好的方式吗?

Dav*_*nan 12

VarIsStr这是一个非常合理的方式.这实现为:

function VarTypeIsStr(const AVarType: TVarType): Boolean;
begin
  Result := (AVarType = varOleStr) or (AVarType = varString)
    or (AVarType = varUString);
end;

function VarIsStr(const V: Variant): Boolean;
begin
  Result := VarTypeIsStr(FindVarData(V)^.VType);
end;
Run Code Online (Sandbox Code Playgroud)

当然,您所看到的更改实际上是由于D2009中的Unicode更改而不是对变体的更改.你的字符串会varUString,又名UnicodeString.当然,VarIsStr也拿起AnsiString/varStringWideString/BSTR/varOleStr.

如果您希望真正忠实地转换Delphi 2007代码,那么您可以编写:

if (VarType(Value) = varUString) and (Value = '') then 
  Exit;
Run Code Online (Sandbox Code Playgroud)

究竟你需要做什么,只有你可以知道,但关键是你必须考虑新到的varUString.


War*_* P 4

更新:特定于字符串以避免异常:

    if VarIsStr(Value) and (Length(VarToStr(v))=0) then ...
Run Code Online (Sandbox Code Playgroud)

Update3:如果您想要更好的性能和更少的字符串堆内存浪费,请尝试此操作。假设字符串长度为 64K。上面的代码执行 VarToStr 并分配大约 64K 的 UnicodeString 堆空间来保存数据,这样我们就可以在 BSTR 的字符串末尾查找 nul 终止符,以及其他类型的 nil 指针。

下面的代码有点奇怪,因为人们通常不会触及变体的内部表示,但大卫指出了这些错误,我重新测试了它,它似乎有效,尽管没有明示或暗示的保证。对这只小狗进行单元测试会很好。在未来的某个日期,如果 Delphi RTL 上帝决定重命名 Variant 结构字段的内部表示,则需要更改下面的代码。

function VarStrEmpty(v:Variant):Boolean;
var
  data:PVarData;
begin
    data := FindVarData(V);
  case data^.VType of
     varOleStr:
            result := (data^.VOleStr^=#0);
     varString:
            result := (data^.VString=nil);
     varUString:
            result := (data^.VUString=nil);
     else
      result := false;
  end;
end;
Run Code Online (Sandbox Code Playgroud)

  • Nick 试图避免当变体无法强制转换为字符串时出现的异常。这就是为什么他需要第一次检查和短路评估。 (2认同)