【问题标题】:Delphi: Pass TObject in array of VariantsDelphi:在变量数组中传递 TObject
【发布时间】:2009-04-15 11:39:05
【问题描述】:

我有一个需要 TObject 类型参数的过程,如下所示:

MyProcedure (const AValue : TObject);

我有一个 Variant 数组,我正在循环调用该过程,如下所示:

  for i:=0 to High(myArray) do
    MyProcedure (myArray[i]);

编译器给出错误提示:“不兼容的类型:TObject 和 Variant”。

我能做些什么来解决这个问题?

更多信息:到目前为止,我一直在变量数组中传递简单类型(字符串、数字、日期)(这些数组通常是不同类型的混合——我最终会传递它们作为数据库存储过程的参数)。现在我还需要(在某些情况下)传递一个 TObject。

传递值最合适的数据类型/结构是什么,可以同时保存简单类型和对象?我想我可以创建我自己的 TParam 类型,它对两者都有一个字段,但我不确定确切的语法。谁有这方面的例子?

【问题讨论】:

标签: delphi variant tobject


【解决方案1】:

Variant 不能包含对象,它只能包含原始类型,例如整数和字符串。

我建议将您的数组更改为您想要的类型而不是变体。如果您不确定所需的对象类型,请创建一个 TObject 数组或您的数组将包含的对象的最低基类。

【讨论】:

  • Delphi 的自定义变体(TCustomVariantType 后代)可以容纳对象。 VCL 中甚至还有这样的示例,请参阅 SqlTimSt.TSQLTimeStampVariantType、FMTBcd.TFMTBcdVariantType。
【解决方案2】:

您不能存储普通对象是一种变体。但是你可以存储接口。

var
  v : Variant;
  i : IInterface;

begin
  v := i; // Works perfectly;
end.

查看变体的类型:

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 }
//varDecimal  = $000E; { vt_decimal     14 } {UNSUPPORTED as of v6.x code base}
//varUndef0F  = $000F; { undefined      15 } {UNSUPPORTED per Microsoft}
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 }
varUInt64   = $0015; { vt_ui8         21 }

如果你真的想要,你可以将 TObject 转换为指向 Integer 的指针并存储它。但我不确定这是否是你真正想要的。

【讨论】:

  • 我同意Gamecat,如果您需要将对象作为变体传递,那么我会考虑使用接口。
【解决方案3】:

我的第一反应是问为什么要将 TObjects 存储在变体列表中,但假设你有充分的理由!

如果您首先设法将 TObject 实例放置在 Array 中,那么您可能放置了指向 Tobject 的指针。在这种情况下,您需要做的是将 Variant/Integer 类型转换为 TObject 例如

for i:=0 to High(myArray) do
    MyProcedure (TObject(myArray[i]));

这应该可以工作,但是与任何类型转换一样,您需要确保 myArray[i] 实际上是指向 TObject 实例的指针,否则可能会发生可怕的事情。

你确定 TList 不会做你想做的事吗?变体实际上是为了存储基本类型,例如字符串、整数、浮点数、布尔值,而不是对象。

【讨论】:

    【解决方案4】:

    我认为使用 Variant 变量和 TOBject 变量创建 TParam 不是一个好主意。比如:

    Tobject = record
      prim: Variant;
      obj: TObject;
    end
    

    可行,但对我来说似乎很乱。 Pascal 不是一种动态类型的语言,我不会尝试将其视为一种语言。我会建议:

    创建另一个函数来处理 Variant,以及拥有

    MyProcedure (const AValue : TObject);
    

    还有

    MyProcedure (const AValue : Variant);
    

    并单独处理您的数据。或者创建一条记录来定义您的数据输入,例如,不要让变体和对象的 TParam 具有类似的内容:

    TStoredProcParm = record
      name: String;
      bought: TDateTime;
    end;
    

    等等。也许您有太多不同的数据,以至于变体/对象路由是最好的,但这似乎有点让人头疼 - 当您的其他代码通过 Variant 数组时,您如何知道哪个变体是哪个以及如何使用每个它们在您的存储过程中?

    【讨论】:

    • 我明白你关于 TParam 记录“混乱”的观点。但是我有办法知道什么时候使用哪个,所以这可能是我在这个项目上最好的解决方案(TObject 值将很少使用)。
    猜你喜欢
    • 2014-07-31
    • 1970-01-01
    • 2016-12-27
    • 1970-01-01
    • 2012-05-01
    • 2011-06-27
    • 1970-01-01
    • 1970-01-01
    • 2011-06-16
    相关资源
    最近更新 更多