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/varString
和WideString/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)