Tag Property

C

C# Learner

How can I achieve something like the following?

private void label_Click(object sender, System.EventArgs e)
{
Label label = (Label)sender;
int number = (int)label.Tag;
}

The second line causes a System.InvalidCastException to be thrown.

Nine Labels have their Click event handlers set to the above method.
Each has its Tag property set at design-time to a number from 0 to 8.

I've tried searching MSDN for info about the Tag property in
who-knows-what-base-class, but it's like trying to find a needle in a
haystack.
 
G

Gaurav Khanna [C# MVP]

Hi!

Tag is inherited from the Control class and is System.Object type.

That said, you could do a convert using the Convert class as shown below:

int number = Convert.ToInt32(label.Tag);

--
Regards,
Kumar Gaurav Khanna
-----------------------------------------------------------------
Microsoft MVP - C#/.NET, MCSE Windows 2000/NT4, MCP+I
WinToolZone - Spelunking Microsoft Technologies
http://www.wintoolzone.com/
OpSupport - Spelunking Rotor
http://opsupport.sscli.net/
Bangalore .NET Users' Group
http://groups.msn.com/bdotnet/
 
C

C# Learner

Gaurav Khanna said:
Hi!

Tag is inherited from the Control class and is System.Object type.

That said, you could do a convert using the Convert class as shown below:

int number = Convert.ToInt32(label.Tag);

That works, thanks.

I don't understand why I can't just cast though. I mean, isn't Tag
made for holding a reference to an object (i.e. an address)? In that
case, wouldn't it just be holding 0x01?

If this is true, it's just holding binary 0000 0001, which should be
"castable", shouldn't it?
 
C

C# Learner

In that
case, wouldn't it just be holding 0x01?

I meant, "For example, if the Tag property is set to 1 at design-time,
wouldn't it just be holding 0x01?"

<snip>
 
J

Jay B. Harlow [MVP - Outlook]

C# Learner,
It really depends on how the designer set the value to 1.

Was it 1 (an integer) or was it "1" (a string)?

It its "1" a string, then the Convert.ToInt32 is the way to go, however if
its truly 1 an integer, then your cast should work. Seeing as your cast was
failing I suspect its "1" a string.

You could put a breakpoint on the failing statement, and use the watch
window to verify what type of value the Tag property is actually holding.

Hope this helps
Jay
 
M

Matthew W. Jackson

The problem is when you type "1" in the designer, it is assuming that "1" is
a string. Therefore, the Tag property does not hold a number, but an
instance of System.String. So in fact Tag actually contains a pointer to a
string "1" somewhere.

System.String cannot be directly cast to an int. Even if it COULD it
wouldn't work in this case.

The reason is due to boxing/unboxing--casting an Object to int will ONLY
work when that Object actually contains a boxed int.

For example, you can do this:

int a = 5;
short b = a;

And you can do this:

int a = 5;
object o = a;
int b = (int)o;

But you cannot do this:

int a = 5;
object o = a;
short b = (short)o;

To make the above code work, you would have to change it to:

int a = 5;
object o = a;
short b = (short)(int)o;

Or

int a = 5;
object o = a;
short b = Convert.ToInt16(o);

The Covnert class handles the casting and unboxing for you, as well as
conversions from strings to numbers (at the expense of
performance--especially if you already know the datatype of the boxed
value).

If you REALLY need to store an int directly in the Tag, you need to modify
the code that the Form designer generated for you. Somewhere in
InitializeComponent() you will see a line like this:

label.Tag = "1";

Which you could change to:

label.Tag = 1;

However, the designer will probably just change it back first chance it
gets. You could also set the value elsewhere (in the Form constructor for
example).

But both of these methods would defeat the purpose of the designer.


Incidentally, one could write a component similar to the ToolTipProvider
that added an IntTag to every control, but I don't think it's worth the
trouble.


I think the best solution is Convert.ToInt32().

However, if you're worried about performance, then:

Int32.Parse((string)label.Tag)

might run a bit faster....but you still have a string-to-int conversion
which isn't all that fast (relatively) to begin with.


Enough babbling on my part though.

--Matthew W. Jackson
 
C

C# Learner

Jay B. Harlow said:
C# Learner,
It really depends on how the designer set the value to 1.

Was it 1 (an integer) or was it "1" (a string)?

It its "1" a string, then the Convert.ToInt32 is the way to go, however if
its truly 1 an integer, then your cast should work. Seeing as your cast was
failing I suspect its "1" a string.

You could put a breakpoint on the failing statement, and use the watch
window to verify what type of value the Tag property is actually holding.

Oops! You are indeed correct: the code created by the designer is
assigning it a string value. I should've looked in
InitializeComponent()!
Hope this helps
Jay

Thanks
 
C

C# Learner

However, if you're worried about performance, then:

Int32.Parse((string)label.Tag)

might run a bit faster....but you still have a string-to-int conversion
which isn't all that fast (relatively) to begin with.

I'm not so worried about performance in this case, and
Convert.ToInt32() will do.
Enough babbling on my part though.

Thanks for sharing!
 

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

Top