Reference a sequence of labels in C#

2019-08-09 08:32发布

问题:

I have message box that asks the user whether they want to restart.

if (MessageBox.Show("Restart?", 
      "Restart and Clear", 
       MessageBoxButtons.YesNo) == DialogResult.Yes)
{
    labels.Text="0"
}

Instead of "labels" I want to use label1, label2, label3, etc. all the way to label60. I could do label1.Text=label2.Text .... = 0 but that would take a while. Is there an easy way to do this, possibly using a for statement?

回答1:

I'd say you could use Control.ControlCollection.Find

for (int i = 1; i <= 60; i++)
{
    label = Controls.Find("label" + i.ToString()) as Label;
    label.Text="0"
}

Not tested but I think this Linq version should do the same

Enumerable
    .Range(1, 60)
    .ToList()
    .ForEach(i => (Controls.Find("label" + i.ToString()) as Label).Text = "0");


回答2:

I believe what you are trying to do is reset every label's text to 0 if so

foreach(Label l in this.Controls.OfType<Label>())
   l.Text = "0";

On a side note, you should try to give your controls meaningful names to help when maintaining your code

Edit

A more robust approach but to make sure you don't reset text that you don't wish to change you could make a subclass of label and then use this class for labels that can be reset

class ResettableLabel : Label
foreach(ResettableLabel l in this.Controls.OfType<ResettableLabel >())...


回答3:

You could add all of your labels to a collection or a list. Then you could easily ForEach the list.

var allLabels = new List<Label>( { label1, label2, label3, ... , label60});
allLabels.ForEach(l=> l.Text = "0");


回答4:

Yes, you could use reflection like this:

for (int i = 1; i <= 60; i++)
{
    var fi = this.GetType().GetField(string.Format("label{0}", i));
    if (fi == null) { continue; }

    fi.SetValue(this, "0");
}

Another approach would be to use the Find method:

for (int i = 1; i <= 60; i++)
{
    var c = this.Controls.Find(string.Format("label{0}", i), true);
    if (c == null) { continue; }

    ((Label)c).Text = "0";
}

In short, there are a lot of ways to skin this cat. Out of the two I provided, the second is going to be more efficient and would probably be my choice.



回答5:

Use reflection:

// using System.Reflection;
for (int i = 1; i <= 60; i++)
    ((Label)this.GetType().GetField("label" + i, BindingFlags.NonPublic | BindingFlags.Instance).GetValue(this)).Text = "0";