在Delphi中,我想确定一个特定的OleVariant是否可以转换为特定的数据类型而不会引发异常,如果它不能。例外情况不适用于程序流程,对吗?
我想要的是这样的,其中Type可以是OleVariant支持的任何东西:
if TryVarAsType(variant, value) then ...
我不想要的是
try
value := Type(variant);
// case where the variant could be converted to a Type
except
// case where the variant could not be converted to a Type
end;
变量无法转换为布尔值的情况只是一个定期发生的正常情况,并不表示任何类型的错误。
答案 0 :(得分:3)
您可以使用VariantChangeTypeEx
函数构建此类函数。
uses
VarUtils,
Variants;
function TryVarAsType( AVariant : OleVariant; const AVarType: TVarType ) :Boolean;
var
SourceType: TVarType;
begin
SourceType:=TVarData(AVariant).VType;
//the types are ole compatible
if (AVarType and varTypeMask < varInt64) and (SourceType and varTypeMask < varInt64) then
Result:=
(SourceType=AVarType) or
(VariantChangeTypeEx(TVarData(AVariant), TVarData(AVariant), VAR_LOCALE_USER_DEFAULT, 0, AVarType)=VAR_OK)
else
Result:=False; //Here you must process the variant pascal types like varString
end;
并像这样使用
TryVarAsType('1',varInteger);
TryVarAsType('s',varInteger)
这仅适用于与ole兼容的Variant类型
varEmpty = $0000; { vt_empty 0 }
varNull = $0001; { vt_null 1 }
varSmallint = $0002; { vt_i2 2 }
varInteger = $0003; { vt_i4 3 }
varSingle = $0004; { vt_r4 4 }
varDouble = $0005; { vt_r8 5 }
varCurrency = $0006; { vt_cy 6 }
varDate = $0007; { vt_date 7 }
varOleStr = $0008; { vt_bstr 8 }
varDispatch = $0009; { vt_dispatch 9 }
varError = $000A; { vt_error 10 }
varBoolean = $000B; { vt_bool 11 }
varVariant = $000C; { vt_variant 12 }
varUnknown = $000D; { vt_unknown 13 }
varShortInt = $0010; { vt_i1 16 }
varByte = $0011; { vt_ui1 17 }
varWord = $0012; { vt_ui2 18 }
varLongWord = $0013; { vt_ui4 19 }
varInt64 = $0014; { vt_i8 20 }
对于其他类型(pascal变体),例如varString
,varAny
,您必须检查源和目标TVarType
并编写自己的测试用例。
更新
正如@David指出的那样,语言环境设置可以为相同的值产生不同的结果,因此您必须将此答案视为初始步骤或提示构建您自己的功能,并且您必须知道在此处导致的语言环境设置问题建议的功能。
答案 1 :(得分:2)
我不知道内置支持会允许动态转换检查失败并显示错误代码而不是异常。
您可以自己手动编写代码,但这样做会在Variants单元中产生无法容忍的代码重复。在这种情况下,我认为使用异常并不比复制依赖于实现的代码更糟糕。
作为RRUZ最常见答案的反例,我提供以下代码:
procedure Main;
var
v: Variant;
i: Integer;
CanConvert: Boolean;
begin
v := '$1';
Writeln(BoolToStr(TryVarAsType(v, varInteger), True));
try
i := Integer(v);
if i>0 then begin
CanConvert := True;
end;
except
CanConvert := False;
end;
Writeln(BoolToStr(CanConvert, True));
end;
输出:
False
True