Assign class() to object() array

This works, but should it? Am I taking advantage of a bug?

dim d() as Dictionary
d.Append( new Dictionary)

dim o() as Object = d

Well dictionary is subclassed from object so you can assign a dictionary to an object. The opposite wouldn’t work though. Or are you asking about something else?

d is an array and so is o. implicit upcasting of arrays is ok, it’s the down casting you can’t do.

Yes, assigning an array of something to an array of object. Dictionary is just my example.

Why do you think that is a bug?

I don’t necessarily, but I’m trying to figure out now why this doesn’t work:

dim d() as Dictionary
d.Append( new Dictionary)

dim v as Variant = d
dim o() as Object = v // TypeMismatchException at runtime

reported here <https://xojo.com/issue/12213>

If not a bug I’d consider it at least a hard limitation.

Thanks Will. That’s a bummer.

[quote=132825:@Kem Tekinay]I don’t necessarily, but I’m trying to figure out now why this doesn’t work:

[code]
dim d() as Dictionary
d.Append( new Dictionary)

dim v as Variant = d
dim o() as Object = v // TypeMismatchException at runtime
[/code][/quote]

It doesn’t work because Dictionary is a subclass of Object but not a subclass of Variant. The way you can assign a value of any type to a variable of type Variant is completely different from assigning an instance of a subclass to a variable declared to hold instances of a superclass. In a nutshell, an array of dictionaries is an array of objects but it isn’t an array of variants.

(This issue has come up here a couple of times over the years.)

Thanks, but that’s not the issue here. I’m assigning the array to a single variant, not an array of variant. I understand why the later won’t work.

This isn’t an array of variants. It’s a single variant holding an array being assigned to an array of a higher type which would otherwise upcast.

OK, I missed that. It may just be a limitation of the variant concept in Xojo.

It seems to me that there should be a ArrayValue or similar added to variant. Once you put an array into a variant it doesn’t seem like you can get it back out unless you use an array of the same type as the array entered. Trying to retrieve the array into an array of type object generates the exception like you mentioned Kem. Interestingly v.objectValue returns an object of type “Array” with no elements, it would seem to me that this should generate an exception? A few quick pokes at the array type with introspection indicates that the Array type has no methods and no properties…

Yet it seems to work under some circumstances, I just havent figured out when.

It works when you are putting the array in the variant back into an array of the same type. When the compiler would have to upcast, however, it generates the type mismatch exception.

dim d() as Dictionary = Array(new Dictionary, new Dictionary, new Dictionary) dim v as Variant = d dim d2() as Dictionary = v //ok, d2 is assigned the array from the variant dim o() as Object = v //not ok, TypeMismatchException is generated at Runtime

No, I mean that I seem to be able to get an array that’s tucked into a Variant into an array of Object sometimes, but I don’t yet understand the circumstances where that’s true. Specifically, I seem to be able to do it under some condition when I’m accessing an array property via Introspection.

Oh, ok. I haven’t tried to access it through introspection yet. I plan to look into it some more tomorrow.

If you can figure out why it works sometimes and not others, please let me know. It might have to do with how the array is assigned (prop = arr vs. prop.Append…), but I can’t narrow it down.

Just as background, we have created serialization/deserialization methods that will serialize a property that holds an array of a known class, but it works with some classes and fails in another.

[quote=132864:@Kem Tekinay]If you can figure out why it works sometimes and not others, please let me know. It might have to do with how the array is assigned (prop = arr vs. prop.Append…), but I can’t narrow it down.

Just as background, we have created serialization/deserialization methods that will serialize a property that holds an array of a known class, but it works with some classes and fails in another.[/quote]

Quite honestly you won’t be able to make it work 100% generically unless its implemented IN the classes themselves.
Really. But have fun trying.
Aaron & I spent about a month working on it and there really are a few roadblocks that prevent this from being possible.
And we could even hack the underlying C++ framework - so we’re way ahead of you on that front.
You’ll run into

  1. deep vs shallow references are an issue and there’s no way an outside module etc can know correctly what to do. SO you need some way to ASK every class “should I copy this deeply or shallow”
    But since EVERY class has to implement that its just as simple to make them implement “serializable” return the data in some std form (JSON, XML, text etc) and append that to the serialized object graph - thats roughly how saving a project works.
    And then the converse to actually reconstitute one from some serialized data.

  2. arrays and variants , arrays in variants, dictionaries holding variants holding arrays and … yeah it gets nasty :slight_smile:

I understand the potential complexity, but what we’re doing is not that complicated.

  1. Classes that can be serialized are registered through a method that takes the Class TypeInfo.
  2. When serializing, we use Introspection to grab the data of each public, readable property.
  3. If the property holds an object, its class must be registered.
  4. If the property is an array of objects, the class that it holds must be registered.
  5. Each item of the array is serialized. (This is where we assign the property to o() as object.)

We don’t attempt to serialize Variants (single or arrays) or Dictionaries. We avoid circular references to make sure we don’t get into an endless loop.

This works perfectly, except in the one case where we get a TypeMismatchException. It makes no sense because other properties that hold other subclasses of the base class work just fine. Our unit tests work just fine. It’s just this one subclass.

I’ll have to examine it in more detail to see what the difference is.