18

我正在使用一个公开了很多Variant属性的 COM 组件,但有时这些值为空。当我尝试将这些值转换为字符串(或其他 Delphi 类型)时,应用程序会引发如下异常:

无法将类型 (Null) 的变体转换为类型 (String)

但是,如果我使用 .net 调用相同的属性并且值为 null,则不会引发异常,并且 null 值将被视为空字符串。

我的问题是有一种方法可以处理来自 Delphi 的这些空值以避免这些异常?

提前致谢。

4

5 回答 5

30

尝试将NullStrictConvert设置为 False。

因为它是一个全局变量,所以我使用它来尽量减少副作用:

var
  OldNullStrictConvert: Boolean;
begin
  OldNullStrictConvert := NullStrictConvert;
  NullStrictConvert := False;
  try
    // code containing conversions
  finally
    NullStrictConvert := OldNullStrictConvert;
  end;
end;

(实际上我已经制作了一个监护人界面。)

注意:在可行的情况下,我更喜欢Warren的代码。

于 2011-05-09T18:34:45.917 回答
20

接受的答案会更改全局设置,并且可能会对您更改之前正在运行的其他代码的操作产生意想不到的副作用。

首先,您可以只使用VarToStrDef,其次,如果您必须提供除此之外的某些功能,那么我会让我的代码调用我自己的函数 MyVarToStr,并这样做:

resourcestring
    SNilValue = '[nil]';


function VarIsAssigned(v:Variant):Boolean; inline;
begin
          result := (v<>Variants.Null) and (not VarIsNull(V));
end;


function MyVarToStr( v:Variant):String;
begin
  if VarIsAssigned(v) then
    result := VarToStr(v)
else
    result := SNilValue;
end;

既然 VarToStrDef 似乎就足够了,我只是想证明最好编写代码并调用自己的代码,而不是尝试“全局更改”VCL/RTL 库代码的默认行为。

于 2011-05-09T23:04:10.897 回答
14

这是记录在案的VarToStr函数行为。没有必要重新发明轮子。

Null 变体是不同的类型(是的,它是一种类型,而不仅仅是一个值),它表示丢失或未知数据。因此,严格来说,常规变体动态类型不应该与Null值一起发生(说明并反映在 RTL 默认值中)。

给定:

var
  V: Variant;
  S: string;

更好的代码

S := VarToStr(V);             { stongly-typed explicit conversion }

比较好的代码

if not VarIsNull(V) then      { program knows what it does, but reproduces RTL behaviour }
  S := V
else
  S := NullAsStringValue;

错误的代码

NullStrictConvert := False;   { smelly, from now on Null variant loses its specifics }
S := V;

更糟糕的代码

try
  S := V;
except on Eaten: Exception do { stinky PHP-style, hiding error instead of fixing it }
  S := NullAsStringValue;
end;

注意:大多数晚期 Delphi.NET 在 Null 变体上表现出完全相同的行为,因此 OP 关于 .NET 的评论值得怀疑。

于 2011-05-10T02:49:22.510 回答
7

VarToStr()并且是将 Null 转换为aVarToStrDef()的正确方法,因为它们会在内部显式检查 Null 值。VariantString

于 2012-05-08T01:48:16.767 回答
4

..from user422039 代码使用 VarToStr 否则 S:=V 依赖于隐式转换,这可能会在不同的环境中产生不同的结果:

S := VarToStr(V);
or
S := VarToStrDef(V, yourdefaultvalue);
于 2012-02-09T07:55:21.043 回答