Variant / Array question

I know that variants should be used with care. I rarely make use of them, but there are places where they make sense. Today I stumbled upon such a use case and I am having a hard time dealing with variants and arrays. Assume following model situation:

  dim a() as integer = array(1, 2, 3, 4)
  SomeFunction(a)

[code]Sub SomeFunction(v1 as Variant)
dim v2() as Variant

if v1.IsArray then
v2() = v1
else
v2.Append v1
end if
End Sub
[/code]

This will result in a TypeMismatchError on v2() = v1. It’s a bad example and my code is much more complex, but it strips down what I don’t understand: Since v1 apparently is an array, how can I assign that to another variant and then treat it like an array (inc. ubound, etc?).

Not exactly same as the details in the original post above, please see if this helps.

Awesome, thanks. I made a function VariantArray(arr as Variant) as Variant() that does what Kem suggested just for each data type:

[code]Function VariantArray(Arr as Variant) As Variant()
dim r() as Variant

if arr.IsArray then
select case arr.ArrayElementType
case variant.TypeBoolean
dim v() as boolean = arr
for i as integer = 0 to v.Ubound
r.Append v(i)
next
case Variant.TypeString
dim v() as string = arr
for i as integer = 0 to v.Ubound
r.Append v(i)
next
case Variant.TypeDouble
dim v() as double = arr
for i as integer = 0 to v.Ubound
r.Append v(i)
next
case Variant.TypeInteger
dim v() as integer = arr
for i as integer = 0 to v.Ubound
r.Append v(i)
next
case variant.TypeObject
dim v() as object = arr
for i as integer = 0 to v.Ubound
r.Append v(i)
next
case variant.TypeSingle
dim v() as single = arr
for i as integer = 0 to v.Ubound
r.Append v(i)
next
case else
//other data types alike…
end select

end if

return r

End Function
[/code]

Why not

  dim a() as integer = array(1, 2, 3, 4)
  SomeFunction(a)

Sub SomeFunction(paramarray v1 as Integer) End Sub

Tried it but it treated the integer array as one element in the paramarray.

Yeah because it SHOULD be

[quote=25935:@Norman Palardy]Why not


  SomeFunction( 1, 2, 3, 4 )

Sub SomeFunction(paramarray v1 as Integer) End Sub [/quote]

And you probably want its counterpart

Sub SomeFunction(v1() as Integer) End Sub

And the paramarray version can just call the array version

Sub SomeFunction(paramarray v1 as Integer) SomeFunction( v1 ) End Sub

Ah didn’t see that change, sorry. Nope, need variants…

I’m having problems with this as well. My Code is blowing up here:

[quote=25900:@Alex von Siebenthal] case variant.TypeObject
dim v() as object = arr
for i as integer = 0 to v.Ubound
r.Append v(i)
next[/quote]

I have a row tag. The variant from the RowTag is an array of DBPhoneNumbers.
I want to iterate through the phoneNumbers for that row in code but I can’t convert the rowTag into an array of variants. I keep getting a TypeMismatchException. The weird thing Is I could have sworn this use to work…

When it was assigned, was the original an array of variant as opposed to, say, an array of string?

(Posting your code would help.)

dim myPhoneNumbers() as DBPhoneNumber = GetPhoneNumbers() dim rowTag as variant = myPhoneNumbers

Then when a user double clicks on the row I want to access it’s row tag. If it is an array, I want to expand it.

dim v as variant = lb.RowTag(row)
  if v.IsArray then
    dim vs() as Variant = ConvertVariantToVariantArray(v) //<-Blows Up In This Method
    for each vp as variant in vs
      ....
    next

The “ConvertVariantToVariantArray” method:

Function VariantArray(Arr as Variant) As Variant()
  dim r() as Variant
  
  if arr.IsArray then
    select case arr.ArrayElementType
    case variant.TypeObject
      dim v() as object = arr    //<- Blows up here
      for i as integer = 0 to v.Ubound
        r.Append v(i)
      next
    case variant.TypeSingle
....

I’ve seen that of late too. Try this:

dim a as auto = arr
dim o() as object = a

Does that work?

This is new to me but it looks like when assigning a Variant holding an array to a variable, the variables type must match exactly.

[code]//this works because the type is specifically DBPhoneNumber()
dim r1() As DBPhoneNumber = lb.RowTag(row)

//Upcasting DBPhoneNumber() to Object() doesn’t work
dim r2() As Object = lb.RowTag(row)
[/code]

Kems trick of the Auto works around this for me though.

dim r() As Object = Auto(lb.RowTag(row))

The part that bothers me is that I could swear that I never use to have to do this.

How else would you write a Serialization class if you couldn’t do this? Obviously a serialization class can have no idea about the class types of what it is serializing. When they added Auto did they break this functionality somehow?

You can’t – a serialization in Xojo class needs to know about each class.

No, as this functionality didn’t (and doesn’t) exist.

That can’t be true because I’ve had a serialization class that knows nothing about what its serializing for a long time now.

Then what’s problem?

The problem is that doing this:

case variant.TypeObject dim v() as object = arr for i as integer = 0 to v.Ubound r.Append v(i) next
Has never blown up in my code due to a TypeCastException and I’m not sure what exactly is different where now it is.
Fortunately the Auto does act as a workaround.

This does work. I don’t get an exception on

dim v() as object = arr

But note that arr is an array defined like that:

Dim arr() As Object

If you define it to be something like:

Dim arr() As MyClass1

you’ll get a TypeCastException.

That has always been that way.