3

I have a object type variable (control .Tag) that I need to cast to a structured type, and change a member in. This is a contrived but representative example:

Public Structure struct_COLOURS
  Dim ILikeRed as boolean
  Dim ILikeGreen as boolean
End Structure

Dim AnObject as Object = (some source that is struct_COLOURS)

DirectCast(AnObject, struct_COLOURS).ILikeRed = True ' This is not valid syntax?!

I don't remember my C syntax very well, but it would be something like this:

(struct_COLOURS*)AnObject->ILikeRed = true;

The point is I can cast an object to something and set members in the resulting cast. It seems as though DirectCast is actually a function and is not casting in the way I would interpret it.

Oddly, if you only want to retrieve a member value, you can use DirectCast:

dim YummyRed AS Boolean = DirectCast(AnObject, struct_COLOURS).ILikeRed

is just fine!

If I cannot cast the way I want, and I cannot change the use of the Tag property (so please don't suggest, it's not an option) to store these structures, what is the fastest way to set members?

2 Answers2

7

It seems as though DirectCast is actually a function and is not casting in the way I would interpret it.

No, that’s wrong: DirectCast isn’t a method, it’s a real language construct, like a cast in C.

However, if you store a structure (= value type) in an object, it gets boxed and, by consequence, copied. This is causing the problem here: you’re attempting to modify a copy, not the original, boxed object.

So in order to change a member of a boxed value type object, you need to copy the object, change its value, and copy it back:

Dim tmp = DirectCast(AnObject, struct_COLOURS)
tmp.ILikeRed = True
AnObject = tmp

Incidentally, the same is true in C#, despite the superficial similarity to the C cast syntax.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • How do I put something in there that isn't boxed but is structured? – Mark Leavesley Aug 19 '11 at 13:44
  • OK. How about I store all my structs in a seperate typed array and the Tag just contains the index? The relationship would be consistent for the life time of the controls. I would need to change a lot of code but moving the data out of the tag object is a longer term objective anyway, just not one I wanted to tackle now. – Mark Leavesley Aug 19 '11 at 13:49
  • @Mark Value types are *always* boxed when stored in an `Object`, there’s no way around that. Storing the index to a global array might be an acceptable solution in your case. – Konrad Rudolph Aug 19 '11 at 13:58
  • My last comment went awol. Why don't I just derive my own controls and make the structure a property or lots of properties. Means a ton of changes I wanted to avoid, but it would mean no object types to worry about everytime I wanted to query the structure. – Mark Leavesley Aug 19 '11 at 14:19
  • @Mark That could be the cleanest solution but it might be overkill. – Konrad Rudolph Aug 19 '11 at 15:14
-2

That's how you should cast - with CType:

Dim myColor As Object = Nothing
        Dim color As Color = CType(myColor, Color)
        color.Name = "red"

Why a struct and not a class?

marko
  • 10,684
  • 17
  • 71
  • 92
  • 2
    No, that’s wrong. First of all, that’s unrelated to the problem. Secondly, `CType` is not preferred here. In fact, `DirectCast` should always be preferred because it’s more restrictive and allows better type checking. Thirdly, your code doesn’t follow good style by declaring `myColor` without initialising it straightaway. – Konrad Rudolph Aug 19 '11 at 13:41
  • A class is overkill if all you want to do is store a collection of variables in an organised fashion. A structure is, or should be, extremely efficient because it just a lump of memory being read in a certain way. Besides, wouldn't a class have to be cast in the same way? – Mark Leavesley Aug 19 '11 at 13:44