使用Delphi管理变量中的空值

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

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

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

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

提前感谢您的帮助。

5个回答

30
尝试将NullStrictConvert设置为False。
由于它是一个全局变量,我使用以下方式来最小化副作用:
var
  OldNullStrictConvert: Boolean;
begin
  OldNullStrictConvert := NullStrictConvert;
  NullStrictConvert := False;
  try
    // code containing conversions
  finally
    NullStrictConvert := OldNullStrictConvert;
  end;
end;

(实际上,我已经将其制作成了一个监护者界面。)

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


@user422039:我喜欢strict,但它与Salvador的问题有什么关系? - Uli Gerhardt
我相信Salvador的问题涉及键盘、椅子和被忽略的文档(请看我的回答,第二个链接非常详细介绍了Null和NullStrictConvert)。 - user422039
1
作为全局变量,NullStrictConvert 不是线程安全的,因此在多线程应用程序中设置它可能会产生不必要的副作用。 - Remy Lebeau

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库代码的默认行为要好。


确实。在可能的情况下,我更喜欢类似于你的解决方案。但有时转换深藏在库代码中,你无法控制。 - Uli Gerhardt
哦,是的。那是我个人标准库函数中的一个辅助程序。我添加了一个定义。 - Warren P

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在处理空变体时表现出完全相同的行为,因此,提问者关于.NET的评论是有问题的。


9

VarToStr()VarToStrDef()是将空的Variant转换为String的正确方法,因为它们在内部显式地检查了Null值。


4

..如果使用VarToStr,来自user422039的代码就不会依赖于隐式转换,从而避免在不同环境下产生不同的结果:

S := VarToStr(V);
or
S := VarToStrDef(V, yourdefaultvalue);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接