How to detect variant array on variant

  1. 3 months ago

    Björn E

    Apr 13 Pre-Release Testers, Xojo Pro Iceland

    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 ?

  2. Michel B

    Apr 13 Pre-Release Testers RubberViews.com
    Edited 3 months ago

    http://docs.xojo.com/VarType
    http://docs.xojo.com/Variant.Type

  3. Björn E

    Apr 13 Pre-Release Testers, Xojo Pro Iceland

    @Michel B http://docs.xojo.com/VarType
    http://docs.xojo.com/Variant.Type

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

    So gives no clues to which it is.

  4. Björn E

    Apr 13 Pre-Release Testers, Xojo Pro Iceland

    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.

  5. Norman P

    Apr 13 Pre-Release Testers, Xojo Pro www.great-white-software.com/b...

    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

  6. Björn E

    Apr 13 Pre-Release Testers, Xojo Pro Iceland

    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.

  7. Alfred V

    Apr 13 Pre-Release Testers

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

  8. Björn E

    Apr 13 Pre-Release Testers, Xojo Pro Iceland

    Both Variant Array and ObjectArray have Ubound I would think ?

  9. Alfred V

    Apr 13 Pre-Release Testers

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

  10. Björn E

    Apr 13 Pre-Release Testers, Xojo Pro Iceland

    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

  11. Michel B

    Apr 14 Pre-Release Testers RubberViews.com

    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.

    dim V as variant = self
    
    Try
      dim s() as string = V
      system.debuglog "String"
      
    Catch e as TypeMismatchException
      System.debuglog "Object"
      
    End Try
  12. Tobias B

    Apr 15 Pre-Release Testers, Xojo Pro Bern, Switzerland
    Edited 3 months ago

    @Alfred V;Hoek can't you iterate through the array and check each membe

    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:

    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

    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?)

  13. Tobias B

    Apr 15 Pre-Release Testers, Xojo Pro Bern, Switzerland
    Edited 3 months ago

    @Michel B 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.

    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.

  14. Christian S

    Apr 15 Pre-Release Testers, Xojo Pro, XDC Speakers Germany

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

  15. Michel B

    Apr 15 Pre-Release Testers RubberViews.com

    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.

  16. @Björn Eiacute;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.

    #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
  17. Tobias B

    Apr 15 Pre-Release Testers, Xojo Pro Bern, Switzerland

    @Björn Eiacute;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.

    I did some more experiments on the missing IsA possibilities. It turns out, VarType() on the object can play that role here!

    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!

    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.

  18. Thom M

    Apr 15 Pre-Release Testers Greater Hartford Area, CT

    @Tobias B 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.

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

    // 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
  19. Michel B

    Apr 15 Pre-Release Testers RubberViews.com

    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 ;)

or Sign Up to reply!