Problems with <VariantArray>.Indexof

In the following example a variant array is populated with some string values which are then looked up in different ways:

dim v1 as Variant, v2 as Variant, vAr() as variant
dim idx as integer, Index1 as integer, Index2 as integer, Index3 as integer

for idx = 0 to 2
  v1 =  "Value-" + str(idx)
  vAr.Append  v1    
next idx

idx = 1
v1 =  "Value-" + str(idx)
v2 = vAr(idx)

Index1 = vAr.IndexOf(v1)
Index2 = vAr.IndexOf(v2)
Index3 = -1
for idx = 0 to 2
  if vAr(idx) = v1 then Index3 = idx
next idx

The expected outcome would be Index1 = Index2 = Index3 = 1
Actual outcome is Index1 = -1, Index2 = Index3 = 1

Encodings are the same in all cases, I checked that.
The same code using string variables and arrays will give the expected result though.

Is there a way to have VariantArray.IndexOf to find any values with same content but different address, or should I file a bug report?
This was tested on Windows 7 Pro with Xojo 2017R3 and Xojo2016R3.

Thanks in advance

It’s funny you mention this as I just ran into it myself. It seems to be treating Variants like objects so it will only match on address, not content.

Thanks for the reply. So I assume you consider this a bug too?

If so, the question would be what to make of it.

I did see Feedback Case #43433 by Tobias Bussmann, but that one is dated April 2016 and has not even been reviewed.

No, I’m not sure this is a bug, it may be by design and it’s easy enough to work around.

If the array is only strings, make it a string array. If it can be mixed, loop through it as you do but compare Type before content.

Well, thanks again and yes, from a pragmatic point of view you are right. So I will just assume behavior by design and write my own extension method which I need for looking up dictionary values (as opposed to keys).

Function VariantIndexOf(extends pDataArr() as variant, pFindWhat as variant) As integer	
        dim iMax as integer = pDataArr.UBound
	for idx as integer = 0 to iMax
		    if pFindWhat.Type = pDataArr(idx).Type then
		      if pFindWhat = pDataArr(idx) then return Idx
		    end if
	next idx
	return -1
End Function

You can put both tests in the same If statement:

if pFindWhat.Type = pDataArr(idx).Type and pFindWhat = pDataArr(idx) then ...

On the other had, if the array is of Auto, this works, so maybe it is a bug.

There was an extra feedbackcase for this. Which got fixed. The case I mentioned for variants (#43433) was created in response to this. And never got reviewed. Maybe something about variants makes it difficult to fix for variants.
The difference between Auto and Variant is that Auto looses it´s ambiguity once a value has been assigned. That could make comparisons more simple in case of Auto as you need not worry about 42 being equal to „42“ or not.
By the way, my quick and dirty approach works well for scalar data types but will fail for objects (which is no problem for me as my usage will always be scalar data) .

[quote=396563:@Silke Arnswald]There was an extra feedbackcase for this. Which got fixed. The case I mentioned for variants (#43433) was created in response to this. And never got reviewed. Maybe something about variants makes it difficult to fix for variants.
The difference between Auto and Variant is that Auto looses it´s ambiguity once a value has been assigned. That could make comparisons more simple in case of Auto as you need not worry about 42 being equal to „42“ or not.
By the way, my quick and dirty approach works well for scalar data types but will fail for objects (which is no problem for me as my usage will always be scalar data) .[/quote]

Variants will willingly convert themselves to just about any other type. Auto doesn’t - you have to do it explicitly - which makes a world of difference.

@Jason Parsley

Still it would be much more intuitive if IndexOf for variant arrays containing string data would compare values rather than adresses.

If the comparison would compare eg. hashes then the results were consistent with Dictionary.Haskey.

At the moment you can have:
Dictionary.HasKey(SomeValue) = True but Dictionary.Keys.IndexOf(SomeValue)=-1

Unfortunately this would break any code that relied on comparing addresses, so it’s unlikely to change.

[quote]At the moment you can have:
Dictionary.HasKey(SomeValue) = True but Dictionary.Keys.IndexOf(SomeValue)=-1[/quote]
The order of elements in a dictionary is not guaranteed to be static, so this would be useless anyway.

@Greg O’Lone

First, thanks for your reply. I know you all have tight schedules:-)

The point I really tried to make is not whether or not this is a bug but that the behavior is very unexpected.
It is different from AUTO and it breaks the assumption that something EQUAL to an array element should be found.

If Xojo wants it to be that way then it would be nice to have a warning in the language reference and maybe close any open feedback cases on the topic by making clear it’s by design. That would have saved me quite some work and frustration.

Btw: While index values on dictionaries are not static, you can use them for a “reverse Lookup” (is this value part of the dictionary and if so, what is it’s key?). That brought me here originally.

If someone is relying on a Variant to track the address of a scalar, they deserve to have their code broken. :slight_smile:

But it this is really a concern, it can be addressed with an optional parameter. compareByValue As Boolean = False