【问题标题】:Managing null values in variants using Delphi使用 Delphi 管理变体中的空值
【发布时间】:2011-08-21 21:48:09
【问题描述】:

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

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

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

我的问题是有办法从 Delphi 处理这些空值以避免这些异常?

提前致谢。

【问题讨论】:

    标签: delphi null delphi-xe variants


    【解决方案1】:

    尝试将NullStrictConvert 设置为 False。

    由于它是一个全局变量,我按如下方式使用它来最大程度地减少副作用:

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

    (实际上我已经用这个做了一个监护人界面。)

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

    【讨论】:

    • @user422039:我喜欢strict,但它与萨尔瓦多的问题有什么关系?
    • 我相信 Salvador 的问题与键盘、椅子和被忽略的文档相关联(请参阅我的回答,第二个链接在 Null 和 NullStrictConvert 上非常冗长)。
    • -1 作为全局变量,NullStrictConvert 不是线程安全的,因此在多线程应用程序中设置它可能会产生不必要的副作用。
    【解决方案2】:

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

    首先你可以只使用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 库代码的默认行为要好。

    【讨论】:

    • 确实如此。如果可能,我更喜欢与您的解决方案类似的解决方案。但有时转换深埋在您无法控制的库代码中。
    • 哦,是的。这是我个人标准库功能之一的帮手。添加了一个定义。
    【解决方案3】:

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

    Null 变体是不同的类型(是的,它是一种类型,而不仅仅是一个值),它表示缺失或 未知 数据。因此,严格说,常规变体动态类型不应该发生在Null 值(illustrated 并反映在 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 的评论值得怀疑。

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        【解决方案5】:

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

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

        【讨论】:

          猜你喜欢
          • 2016-12-24
          • 1970-01-01
          • 1970-01-01
          • 2019-09-16
          • 1970-01-01
          • 1970-01-01
          • 2011-04-06
          • 2012-09-05
          • 1970-01-01
          相关资源
          最近更新 更多