Sorry for the basic question, but...

G

Guest

I am "learning" C# and have run into a problem that, though I can work around
it, I would like to know what the *right* way to handle the issue is.

I have created an "Info" struct and assigned certain default values to it.
I have assigned this struct to a TreeView node via the Tag field. In my
"AfterSelect" processing call, I am casting the node tag value to my "Info"
struct. When I look at the fields they are set to the default values that I
set earlier at instantiation time.

If I change the values in the "Info" struct, though, when the "AfterSelect"
callout is returned from and called again, the values are reset back to the
previous default values.

It looks to me that a new object is being created somewhere along the line,
such that in my "AfterSelect" routine I am changing the values of a "new"
object, and no the one initially set as the Tag value of the TreeView node.

My question is, how can I set the Tag of the TreeView control (or any other
control) to "point" to the struct I created at instantiation time? I only
want one copy floating around, and want changes to the object to persist
across each callout.

The answer is probably very simple (and the question itself gives my
newbieness away<g>).

Any help would be appreciated.

Thanks in advance,
-Brian
 
J

Jon Skeet [C# MVP]

Brian said:
I am "learning" C# and have run into a problem that, though I can work around
it, I would like to know what the *right* way to handle the issue is.

Excellent - that's exactly the right attitude :)
I have created an "Info" struct and assigned certain default values to it.
I have assigned this struct to a TreeView node via the Tag field. In my
"AfterSelect" processing call, I am casting the node tag value to my "Info"
struct. When I look at the fields they are set to the default values that I
set earlier at instantiation time.

Yup, they would be. That's because structs are value types. When you
set the Tag property of the node, you're creating a new copy with the
same values.
If I change the values in the "Info" struct, though, when the "AfterSelect"
callout is returned from and called again, the values are reset back to the
previous default values.

It looks to me that a new object is being created somewhere along the line,
such that in my "AfterSelect" routine I am changing the values of a "new"
object, and no the one initially set as the Tag value of the TreeView node.

My question is, how can I set the Tag of the TreeView control (or any other
control) to "point" to the struct I created at instantiation time? I only
want one copy floating around, and want changes to the object to persist
across each callout.

The answer is probably very simple (and the question itself gives my
newbieness away<g>).

The answer is almost certainly that you should use a class instead of a
struct. Do you particularly *need* value type semantics elsewhere? You
should normally be create your own structs only very rarely - almost
every type you create should (for most apps) be classes.

See http://www.pobox.com/~skeet/csharp/memory.html and
http://www.pobox.com/~skeet/csharp/parameters.html

for more information.
 
C

Christof Nordiek

Hi Brian,

what is the "right way" to hanle it, depends on, what the "Info" really is.
My question is, how can I set the Tag of the TreeView control (or any
other
control) to "point" to the struct I created at instantiation time? I
only
want one copy floating around, and want changes to the object to persist
across each callout.

If this is the nature of your Info-type, then it surely should by a
reference-type.
Make a class instead of a struct.
It looks to me that a new object is being created somewhere along the
line,
such that in my "AfterSelect" routine I am changing the values of a "new"
object, and no the one initially set as the Tag value of the TreeView
node.

Since your Info-type is a struct and therefore a valuetype and the Tag
property
is of Type object wich is a reference type, the cast to Info is a unboxing
conversion,
wich means, you get an copy of the boxed instance.
If you want to change the Tag property, (and the Info-type has to be a
valuetype), then you've
got to assign the changed value back to the object instance.

Christof

PS: A very good explanation of valuetype <-> referencetype you can find at:
http://www.pobox.com/~skeet/csharp/memory.html
 
G

Guest

Thanks Jon for your quick reply!

No, I do not need to use structs instead of classes. I came from an
assembler and C background - and structs seem "natural" to me<g>. I
remembered reading in "Inside C#" that structs were not objects - and hence I
presumed that they would be more effecient - if used wisely (which I
evidently was not<g>).

Just to make sure I am really clear on this, the issue is that since the
"Tag" member is of type Object, it "boxes" the struct into an object before
passing it merrily along - this all makes sense to me (hopefully that is
right). Yet, how does one use the Tag field (in numerous controls) to pass,
say, pointers and the like? I know this is "unsafe" code - and I will avoid
doing so - but it would be nice to know how to pass an address to a
structure, array (C style), position in memory, etc. What happens under the
covers when you set the Tag field to a numeric value? (I guess I could look
at the MSIL and see...).

Maybe I am just really missing the proverbial object boat here<g>?

Thanks again!
-Brian
 
G

Guest

Thanks Christof, for your reply.

It looks like my 'C' background and structs got me in trouble<g>. I'll
convert it to a class and all should be well.

Thanks again!
-Brian
 
J

Jon Skeet [C# MVP]

Brianta said:
No, I do not need to use structs instead of classes. I came from an
assembler and C background - and structs seem "natural" to me<g>. I
remembered reading in "Inside C#" that structs were not objects - and hence I
presumed that they would be more effecient - if used wisely (which I
evidently was not<g>).

Just to make sure I am really clear on this, the issue is that since the
"Tag" member is of type Object, it "boxes" the struct into an object before
passing it merrily along - this all makes sense to me (hopefully that is
right).

Yup, that's right.
Yet, how does one use the Tag field (in numerous controls) to pass,
say, pointers and the like?

To be honest, I wouldn't like to say - I've never used pointers in
anger before. I basically haven't needed to.
I know this is "unsafe" code - and I will avoid
doing so - but it would be nice to know how to pass an address to a
structure, array (C style), position in memory, etc. What happens under the
covers when you set the Tag field to a numeric value? (I guess I could look
at the MSIL and see...).

Maybe I am just really missing the proverbial object boat here<g>?

If you set the field to a numeric value, that numeric value will be
boxed.

Basically, if you want reference type semantics, use a reference type
:)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Top