简体   繁体   English

Delphi:在Variants数组中传递TObject

[英]Delphi: Pass TObject in array of Variants

I have a procedure that expects a parameter of type TObject, something like this: 我有一个程序,需要一个TObject类型的参数,如下所示:

MyProcedure (const AValue : TObject);

I have an array of Variant that I'm looping through to call the procedure, something like this: 我有一个Variant数组,我正在循环调用该过程,如下所示:

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

The compiler gives an error saying: "Incompatible types: TObject and Variant". 编译器给出错误说:“不兼容的类型:TObject和Variant”。

What can I do to get around this? 我该怎么做才能解决这个问题?

More information: Up until now, I have been passing simple types (strings, numbers, dates) in variant arrays (the arrays are typically a mix of different types -- I'm eventually passing them as parameters to a database stored procedure). 更多信息:到目前为止,我一直在变量数组中传递简单类型(字符串,数字,日期)(数组通常是不同类型的混合 - 我最终将它们作为参数传递给数据库存储过程)。 Now I need to also (in certain cases) pass a TObject. 现在我还需要(在某些情况下)传递一个TObject。

What is the most appropriate data type/structure to pass the values, that can hold both simple types and objects? 传递值的最合适的数据类型/结构是什么,它可以包含简单类型和对象? I guess I could create my own TParam type that has a field for both, but I am not sure of the exact syntax. 我想我可以创建自己的TParam类型,它有两个字段,但我不确定确切的语法。 Anyone has an example of this? 有人有这方面的例子吗?

A Variant cannot hold objects, it can only contain primitive types such as integer and string. Variant不能保存对象,它只能包含整数和字符串等基本类型。

I would suggest changing your array to be of the type you want rather than variant. 我建议将您的阵列更改为您想要的类型而不是变体。 If you are not sure of the object type you want then create an array of TObject or the lowest possible base class of the objects that your array will hold. 如果您不确定所需的对象类型,则创建一个TObject数组或数组将保存的对象的最低基类。

You can't store plain objects is a variant. 你不能存储普通对象是一种变体。 But you can store interfaces. 但是你可以存储接口。

var
  v : Variant;
  i : IInterface;

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

Look at the types for the 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 }
//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 }

You can if you really want, cast TObject to Pointer to Integer and store that. 如果你真的想要,可以将TObject转换为Pointer to Integer并存储它。 But i'm not sure if that's what you really want. 但我不确定这是不是你真正想要的。

My first reaction is to ask why you are storing TObjects in a list of variants, but assuming you have a good reason! 我的第一反应是问你为什么要将TObjects存储在变体列表中,但假设你有充分的理由!

If you managed to place your TObject instance in the Array in the first place then you probably placed the pointer to the Tobject. 如果您设法将TObject实例放在数组中,那么您可能会将指针放在Tobject上。 In that case what you need to do is typecast the Variant/Integer as a TObject eg 在这种情况下,您需要做的是将Variant / Integer作为TObject进行类型转换

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

This should work, however as with any typecasting it is up to you to ensure that myArray[i] is actually a pointer to a TObject instance or horrible things might happen. 这应该可行,但是与任何类型转换一样,由您来确保myArray [i]实际上是指向TObject实例的指针或可能发生的可怕事情。

Are you sure a TList would not do what you want. 你确定TList不会做你想要的。 A variant is really meant to store fundamental types such as string, integer, float, boolean not Objects. 变体实际上意味着存储基本类型,例如字符串,整数,浮点数,布尔值而不是对象。

I don't think it's a good idea to create a TParam with a Variant variable a TOBject variable. 我不认为用Variant变量和TOBject变量创建TParam是个好主意。 Something like: 就像是:

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

Would work but it seems very messy to me. 会工作,但对我来说似乎非常混乱。 Pascal is not a dyanmically typed language and I woudn't try and treat it as one. 帕斯卡不是一种语言类型的语言,我不会尝试将其视为一种语言。 I would suggest either: 我建议:

Create another function to handle Variant, so as well as having 创建另一个函数来处理Variant,以及拥有

MyProcedure (const AValue : TObject);

also have 也有

MyProcedure (const AValue : Variant);

and handle your data seperately. 并单独处理您的数据。 Or create a record that defines your data inputs, for example instead of having TParam of variant and object have something like: 或者创建一个定义数据输入的记录,例如,不要让变量和对象的TParam具有如下内容:

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

and so on. 等等。 Maybe you have so much different data that the variant/object route is the best but it seems like a bit of a maintenance headache - when your other code gets passed an array of Variant how do you know which variant is which and how to use each of them in your Stored proc? 也许你有这么多不同的数据,变量/对象路由是最好的,但它似乎有点维护头痛 - 当你的其他代码传递一个Variant数组时,你怎么知道哪个变量是哪个以及如何使用每个变量他们在你的存储过程中?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM