How to detect variant array on variant

How do we detect variant Array on a variant ?

So if I have a Variant variable, which can contain anything…and I check what it contains and find that it contains either ObjectArray or VariantArray.

(since both return same code with the VarType function).

So ok on each Element how would I check if it is Variant or Object ? Isa operator does not work to ask if it is Variant. And if I do Isa Object then both return true.

So question is how would I know if it is Variant or some other Object ?

http://documentation.xojo.com/api/language/vartype.html
http://documentation.xojo.com/api/data_types/variant.html#variant-type

[quote=432623:@Michel Bujardet]http://documentation.xojo.com/api/language/vartype.html
http://documentation.xojo.com/api/data_types/variant.html#variant-type[/quote]

Like I posted above then those both return same code for ObjectArray and VariantArray

So gives no clues to which it is.

This gets worse… there are more cases of this:

Dim v as Variant = 23
Dim a as Object = v

Just this simple example then as far as I know there is no way to Tell if a contains Variant there or some other object.

Since technically Variant is a object but you cannot do Isa on Variant. And Variant.Type will tell you its object since Variant is a object. And if you do Isa Object then you get True always since both Object and Variant are objects after all.

Don’t use variants ?
I know a lot of people use dictionaries of variants, arrays of variants, etc instead of defining classes to model their data but this comes at a cost

I wish ! but sometimes that is not option like when using “Generic” classes like Dictionary and other things or creating such generic structure.

Of course the Right way would be to use Generics ! But Xojo never got into this century with Generics! But I still hold hope on that if I wait another 20 years maybe. All jokes dropped then I would even settle for “Poor mans” Generics at this point, meaning Generics that are just Object based and would not handle basic types like Integer and all that. Even if it is a lot worse than the full thing then it covers very high % of the usages.

If it is a variant array, can’t you check the UBound? Just a thought, …

Both Variant Array and ObjectArray have Ubound I would think ?

I mean, can’t you iterate through the array and check each member for a varType or arrayType (also considering the plugin SDK)?

But VarType returns same value for Variant and Object. So Iterating through them won’t give me any info since both Variant and Object will return 9 from the VarType

Norman often said that Variants are evil. Auto is probably better.

There is yet something else you can do. It is not the purest of code, since we are not supposed to rely on the error management system, but it works.

[code]dim V as variant = self

Try
dim s() as string = V
system.debuglog “String”

Catch e as TypeMismatchException
System.debuglog “Object”

End Try[/code]

AFAIK there is no way (from Xojo Code - there is GetVariantArrayValueMBS to the help) to iterate an Array of Objects stored in an Variant w/o knowing the exact type. While you can normally upcast an array of ClassXYZ to an array of Object, iterate that and use IsA on the content, that is not possible if the ClassXYZ array is stored inside a Variant:

[code]Dim pa() As Pair //using Pair as Object subclass example
pa.Append 1:“A”
pa.Append 2:“B”

Dim oa() As Object
oa = pa //no problem

If oa(0) IsA Pair Then Break //breaks

Dim v As Variant
v = pa

pa = v //ok, the type maches exactly

oa = v //nope, TypeMismatchException here

If oa(0) IsA Pair Then Break //we don’t get that far[/code]

and even if this would work, you can not test for Variant arrays using IsA Variant (did not find a Feedback ticket on that - would you mind to create one?)

for intrinsic types, you can simply make use of Variant.ArrayElementType as a specific test for the type and assign to the correctly typed array. For Object arrays, this is not possible but a try-and-error approach like you sketched out could work if you can guess candidate types.

As a variant is just an object with a few internal wrapper classes, there should be no need to know for an array type.

Personally, I try to stay as far as I can from variants, apart when I use a dictionary. In a strong typed language such as Xojo, variants are incongruities anyway.

@Björn Eiríksson — If an array of variants (or objects) is stored inside a Variant, then its vartype should be TypeArray + TypeObject. Then you can try to cast it to variant(), e.g.

[code]#pragma BreakOnExceptions false

dim v() as Variant
dim o() as Variant

try
v = myArray
catch
end try

if v=nil then
try
o = myArray
catch
end try
end if

//Then use v or o, whichever is not nil[/code]

[quote=432625:@Björn Eiríksson]This gets worse… there are more cases of this:

Dim v as Variant = 23
Dim a as Object = v

Just this simple example then as far as I know there is no way to Tell if a contains Variant there or some other object.

Since technically Variant is a object but you cannot do Isa on Variant. And Variant.Type will tell you its object since Variant is a object. And if you do Isa Object then you get True always since both Object and Variant are objects after all.[/quote]
I did some more experiments on the missing IsA possibilities. It turns out, VarType() on the object can play that role here!

[code]Dim v As Variant = 23

If v IsA Object Then Break //yes, Variant is a Object subclass

Dim o As Object = v //pass it along as such

’ If o IsA Variant Then Break // does not compile: “There Is no Class With this name”

Dim ti As Introspection.TypeInfo = Introspection.GetType( o )
If ti = Nil Then Break // returns nil?!

MsgBox Str(VarType(o)) //shows 3 = Variant.TypeInt64 - not the expected 9 = Variant.TypeObject!
Dim v2 As Variant = o //works w/o a cast

MsgBox v2 //there it is again!
[/code]
In the result you can store an array of Variant in a Variant but not a Variant in a Variant. Still if stored in a Variant, you cannot distinguish an array of Variant from an array of Object w/o guessing and exceptions.

Fortunately, this is incorrect. The workaround is stupid though.

[code]// This works
Dim Dicts() As Dictionary
Dim Objs() As Object = Dicts

// And this works
Dim Var As Variant = Dicts
Dim Temp As Auto = Var
Objs = Temp

// This doesn’t work
Var = Dicts
Objs = Var[/code]

One can also cast the variable to string, and if it is an object, an error will be raised.

But the best way would be not to use variants :wink: