2

To make a long story short, I needed a property of a button to act as a "secondary text property" and retain the original .Text value of a button, and the only String property that wasn't ReadOnly was the .Name property.

I was sure it was going to break on runtime (as tons of code references the name of the control) but just for kicks, I wanted to run it and see what it would do.

I my shock and surprise, IT DIDN'T BREAK! And it actually served my purpose of temporarily holding the original text of the button, in time for me to retrieve it again.

Thus my two questions

(like the surprised kid after he pushed a glass plate on the floor):

  1. Why didn't it break?
  2. And why shouldn't I do it again?

I have a few guesses, but I wouldn't know how to confirm them, so this is my first venture for answers:

  1. I was thinking one possibility is that the .Name property "already served its purpose" by runtime as the code is already compiled, and all references are already made to the instance, and therefore, altering the .Name property does nothing in runtime. But that almost seems too simple an answer.

  2. Maybe I was not actually changing the property, but that seems a silly thing to consider since I was able to retrieve the value.

  3. I finally considered that I've entered the twilight zone and I'll be hunted down and imprisoned by Microsoft for not learning the moral lesson of following proper coding conventions. (Sarcasm; no need to edit my post for this)

I'm inclined to think #1 is the answer, but it seems too simple, and I can't help but think that I'm going to get scolded for messing with it.

Any insight or notes about conventions (even a slap on the wrist) would be appreciated.

Added code example:

(NOTE: I now understand .Tag is a better to use than .Name for this purpose, but this is still a good example for my question.)

Private Sub btn_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs)
    Dim btn As Button = DirectCast(sender, Button)

    'Make sure to only pull the text when it actually has text.
    If btn.Text > " " Then
        btn.Name = btn.Text
    End If

    btn.Text = String.Empty

    'Set flags to center text on button
    Dim flags As TextFormatFlags = TextFormatFlags.HorizontalCenter Or TextFormatFlags.VerticalCenter Or TextFormatFlags.WordBreak   'center the text

    'Render the text onto the button
    TextRenderer.DrawText(e.Graphics, btn.Name, btn.Font, e.ClipRectangle, btn.ForeColor, flags)
End Sub
5
  • 1
    What type of button? ASP.NET web forms? WinForms? WPF? Maybe show some code.
    – John Wu
    Commented May 2, 2020 at 2:36
  • @JohnWu Ah yes, I should have specified. WinForms. I'll update the post with the code I'm using.
    – Hawkeye
    Commented May 2, 2020 at 4:22
  • 5
    Are you aware of the Tag property? That is a far better place to put information that doesn't fit anywhere else.
    – John Wu
    Commented May 2, 2020 at 6:42
  • Wow! I was not! I don't know how I missed it. I'll have to check that out when I get back to the office. Thanks!
    – Hawkeye
    Commented May 2, 2020 at 6:50
  • @JohnWu Thanks for pointing out the .Tag property. When looking for a property to use, I had overlooked it because it was an Object, but understanding its intended use makes it useful in my case, and I may actually have good use for it in the future, storing other Objects.
    – Hawkeye
    Commented May 5, 2020 at 15:40

3 Answers 3

3

Name is used by the designer.

Usually you do not have the need to find a control by name, or identify a control by name, in runtime. If that is the case, then, arguably Name already served its purpose (being used by the designer).

A reason to not mess with it? How about showing intent. It might not be clear to the reader of your code that Name may hold the text of the control temporarily. In fact, what if you need to store something else temporarily and go for Name again? Since there is nothing saying that you are using Name this way, and given enough time for you to forget, or if the code is being maintained by another person, that might introduce some bugs.

Of course, you may use Name in runtime in other ways, without losing the idea that it identifies the control. For example, if you have a single event handler for multiple controls (which might be the case if you added such controls in runtime, or even in the designer, if it makes sense to reuse the same code for all of them), you may use name to identify them. Another thing you can do is use the name as key in a dictionary.

If you need to temporarily hold the text, you could use a local variable or a field… if this needs to be attached to the control (aside from the dictionary idea, which seems like too much overhead for this), then the usual course of action is create a custom control that either sub-classes or wraps the text box (in this case).

I believe you want a text box with some custom rendering. In that case, a custom control seems like a good idea. Let the control handle its own rendering. Alternatively, if the intention was to allow the user to write in the text box and then hide it… well, hide it (Control.Visible = false). You may consider disabling it too. And yes, having a custom control that can show a text box or some pretty rendered text and switches between on demand is good idea too.

1
  • It does seem that the consensus is the name property has (for the most part) served it's purpose in runtime, but I agree with your list of possible downfalls. I did consider using a custom control, but all I really wanted to do was create an extension for buttons that allowed me to disable (.Enabled = False) a button with some custom formatting. As it is, I had no control over the disabled font color (I had to re-render the text to grab the color I had set in my extension). But as JohnWu suggested, the tag property would be able to do the same job. Thanks for the detailed reply!
    – Hawkeye
    Commented May 5, 2020 at 15:34
1

*#1 for sure. If it wasn't for Reflection it would have been discarded at the link phase (or equivalent). You'll probably find this kind of thing breaks down when you use stuff that's dynamic like the .NET API and such like.

Seems like a bad idea in principle, if only because you're a) using something for a purpose it wasn't intended for and b) doesn't have a name that reflects the use. Neither of which are crimes, just bad ideas worthy of tdwtf.com

3
  • I added a sample of some code I was using for testing. Are you saying that when I call btn.Name that it is using reflection?
    – Hawkeye
    Commented May 2, 2020 at 5:22
  • It may not be actually using reflection, but mostly things from the source code are discarded during or shortly after the compilation phase (or linker) depending on how public they are. I was guessing that the only reason it's there is for reflection-type things. That said, I think I could be wrong. If you have an collection of controls and want to ID one of them at runtime, the name seems a reasonable way to be able to tag and identify them so I'm kind of backing away from my answer a bit. Commented May 2, 2020 at 6:24
  • Having access to the name can be useful but I don't think I'd ever change it. For example, one time I used the control names as an index to the content manager so customers could provide custom or multi-lingual text. If a control was named "cm_xyz_LaunchMissleButton" any content named xyz_LaunchMissleButton would be looked up and applied to the control text. In this case the name was useful at runtime. Commented May 2, 2020 at 6:31
0

Why didn't it break?

Either because it’s not used or because your test didn’t exercise the code that uses it.

And why shouldn't I do it again?

Because this is semantically evil. If it’s called Name it should have something to do with a name.

2
  • I would tend to agree about the evil of using .Name for anything other than the control name, but I was hoping it a more "Official" explanation as to some programmatic consequences. I can say that in all my testing of the typical use of a button, it worked!
    – Hawkeye
    Commented May 2, 2020 at 5:05
  • It’s mostly used in code generation. You’re supposed to use this to give your button instance a descriptive name. Commented May 2, 2020 at 5:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.