变种总是很有趣,是吗?
我正在研究D2007中最后一个将其迁移到Delphi XE的遗留应用程序。
变体在过渡期间发生了很大的变化。
这行代码:
if (VarType(Value) = varString) and (Value = '') then
Exit;
返回True并在D2007中退出,但在Delphi XE中没有。
我已将其更改为:
if VarIsStr(Value) and (VarToStr(Value) = '') then
Exit;
我不相信这是“最好的”方式。 Variants单元没有特定的调用来执行此操作,我当然记得这对于过去的人来说是一个问题。但是,搜索显示没有库函数或任何其他可接受的方式。
是否有“正确”或更好的方式?
答案 0 :(得分: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;
您所看到的变化当然是由于D2009中的Unicode更改而非变体的更改。您的字符串将为varUString
,即UnicodeString
。当然,VarIsStr
也会选择AnsiString/varString
和WideString/BSTR/varOleStr
。
如果您希望真正忠实地转换Delphi 2007代码,那么您可以写下:
if (VarType(Value) = varUString) and (Value = '') then
Exit;
您需要做什么,只有您可以知道,但关键是您必须考虑新到达的varUString
。
答案 1 :(得分:3)
更新:特定于字符串以避免异常:
if VarIsStr(Value) and (Length(VarToStr(v))=0) then ...
Update3:如果你想要更好的性能和更少的字符串堆内存浪费试试这个。 想象一下,这些字符串的长度是64K。上面的代码执行VarToStr并分配大约64K的UnicodeString堆空间来保存数据,这样我们就可以在BSTR的字符串末尾查找nul终结符,并查找其他类型的nil-pointers。
下面的代码有点奇怪,因为一个人通常不会进入变体的内部表示,但David指出了这些错误,我重新测试它并且它似乎有效,但是没有保证或默示。这只小狗的单元测试会很好。在未来的某个日期,如果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;
答案 2 :(得分:0)
变体可以是数字或字符串。
当Variant(Number)具有负值(-15)时可能会出现问题。
也是你的行
(VarType(Value) = varString) and (Value = '')
我总是要(
)
((VarType(Value) = varString) and (Value = ''))
答案 3 :(得分:-1)
if VarToStrDef(value, '') = '' then
我的诀窍。