4

I have rewritten this question because not everyone understood. Hope it's ok, it's the same main problem.Very sorry

I have a winform with 15 progress bars called: "baraClasa1", "baraClasa2", "baraClasa3" ... "baraClasa15". I have to assign the .VALUE property (as in int) to all of them, from some database records. (The records access the different values from different time periods) I was thinking that maybe it is possible to use a loop to assign the .Value property to all of them by doing something like:

for(int i=0; i<value; i++)
{
   "baraClasa+i".Value = 20 + i;  
}

Is it possible to compose the name of the variables like that?

I don't know much about dictionaries, lists but looking into. If nothing works il just do the ugly:

int value = 20;
baraClasa1 = value;
baraClasa2 = value +1;....

Thank you for all help

Chris Snow
  • 23,813
  • 35
  • 144
  • 309
Vantalk
  • 367
  • 2
  • 5
  • 21
  • I don't think c# can do dynamic variable creation, your best bet is to use maybe collections or arrays. – unlimit Jan 03 '14 at 16:39
  • Unless `variable` is, in fact, an array or other indexed collection, then `[]` is meaningless. – Grant Thomas Jan 03 '14 at 16:39
  • 1
    Rethink your design. An array is the way to go. Variable names are entirely for giving the developer a hint on what the purpose of the variable is. The program logic should not depend on variable names. – O. R. Mapper Jan 03 '14 at 16:40
  • A dictionary would get you close to the same result. Calling an element would be `dict["variableName"]` http://msdn.microsoft.com/en-us/library/xfhwa508(v=vs.110).aspx – Felix Castor Jan 03 '14 at 16:43
  • @FelixCastor: While being aware that `"variableName"` in that case is not actually (at least not automatically) a variable name. – O. R. Mapper Jan 03 '14 at 16:45
  • Right but as I said it's close. If he wants to call say `x_i` where i is some integer he can simply construct the string `str = "x_"+i.ToString()` and throw that in the `dict[str]`. – Felix Castor Jan 03 '14 at 17:39
  • @FelixCastor: Sure - the OP just needs to be aware that after what you described, using variable named `x_2` (w.l.o.g.) will not be possible automatically. Or if it is (because such a variable was declared somewhere), that the value of that variable will in the general case be totally unrelated to the value of `dict["x_2"]`. That may not seem logical at first in case he or she is coming from the realm of interpreted languages. – O. R. Mapper Jan 03 '14 at 18:26
  • I'll try looking in the dict[] thing.. I hoped there would of been a Run(string) command like in sql where you can concatenate with variables – Vantalk Jan 03 '14 at 18:38

8 Answers8

5

You have to do a little reflection.

    public string variable0, variable1, variable2, variable3, variable4, variable5;

    private void button1_Click(object sender, EventArgs e)
    {
        for (int i = 0; i < 6; i++)
        {
            //pretending my variable names are variable1, variable2.. ("variable" is NOT an array! just the "assign" variable)
            System.Reflection.FieldInfo info = this.GetType().GetField("variable" + i.ToString());

            // replace "testing" with the value you want e.g. assign[i]
            info.SetValue(this, "testing");
        }

        // Do something with your new values
    }

No need to use reflection with the updated question. The control collection has a built in find for getting a control by the name string.

 for (int i = 0; i < 6; i++)
 {
   ProgressBar bar = (ProgressBar)this.Controls["baraClasa" + i.ToString()];
   bar.Value =  50;
 } 
  • 1
    Performance and otherwise considerations aside, this will work only for fields, not for local variables. – O. R. Mapper Jan 03 '14 at 17:35
  • Correct. His last edit said they are control names so this will do the trick. I agree that a redesign would be a better approach but sometimes that is not an option. – Bradley Gatewood Jan 03 '14 at 17:46
  • I believe that in this example I can only change the .Text property of the control? – Vantalk Jan 03 '14 at 18:01
  • Actually with your updated question you don't even have to use reflection. You can just find them by the string value in the control collection. I'll update my answer. – Bradley Gatewood Jan 04 '14 at 02:33
  • I will check into this later today and let you know how it went – Vantalk Jan 04 '14 at 12:41
  • Very weird.. I get an "object reference not set to an instance" error at the bar.Value line. I checked the name of the bars, also tried with a specific name outside of loop. This does seem like the way to go about it so I'll keep exploring and mark the answer as valid once it works. – Vantalk Jan 05 '14 at 09:05
  • Your last example was very good but at start I didn't notice a few things that stopped it from working. First i was equal to 0 in your loop (and I hadn't any "baraClasa0"). Also I've put my controls in a groupbox so the line would be this.groupbox1.Controls.. Thank you for the answer – Vantalk Jan 05 '14 at 11:35
4

This is a design problem. Create a collection for items with common use (like progress bars for that matter) and iterate over the collection to perform actions on them.

If these are prorgress bars you might want to use an event-driven design (another link) to update their progress, meaning that each time a bar has made some progress, the event for the progress will send an update only to that bar, and not iterate over the entire list.

You may want to read an introduction to event driven programming in C# before re-factoring your code.

Reut Sharabani
  • 30,449
  • 6
  • 70
  • 88
  • 1
    Values are taken from a database from previous days, depending on the hour selected.. There isn't much event-driven design that I can think of – Vantalk Jan 03 '14 at 17:02
  • Still, you should be creating a collection to perform the operations as batch (you're right, event driven design is not necessary given your case). You can re-use the collection on every selection, so you don't have to re-create it. If the collection is found out to be different every time, then event-driven design may still apply after all. – Reut Sharabani Jan 03 '14 at 17:13
3

It really isn't possible in C# to refer to local variables in a dynamic fashion as you are trying to do. Instead what you would do in C# is store the value in a dictionary where the key can be generated in a dynamic fashion.

For example let's say all of your variable1, variable2, ... variableN were of type int. Instead of

int variable1 = 0;
int variable2 = 0;
...
int variableN = 0;

You would instead do the following

Dictionary<string, int> map = new Dictionary<string, int>();
for (int i = 0;  i < N; i++) {
  map[i.ToString()] = 0;
}

If the values are a of a fixed number and always linear in progress it may make sense to use an array instead of a dictionary

int[] array = new int[N];
for (int i = 0; i < N; i++) {
  array[i] = 0;
}
JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
2

You can't do it that way. You need an array. Every time you notice yourself having a variable2, you need an array. You may not know it yet, but you do.

nvoigt
  • 75,013
  • 26
  • 93
  • 142
2

No, you can't do it in C#, it's syntactically impossible. But if you want access form controls which has different names like this you can do the following:

for(int i=0; i<20; i++)
{
  var name = "variable" + i;
  this.Controls[name].Text = "etc..." // here you can access your control
}
Selman Genç
  • 100,147
  • 13
  • 119
  • 184
  • `it's syntactically impossible` It most certainly is not. It's difficult, and almost always a bad idea, but it's most certainly not impossible. You could do it through reflection if the variables are instance fields, you could create an expression tree to handle most cases, and if worst comes to worst, you can always use `unsafe` to do...pretty much anything. – Servy Jan 03 '14 at 16:47
  • @Servy, really? You think it's possible with reflection? I don't know how to do this with reflection – Selman Genç Jan 03 '14 at 16:49
  • It would depend on the specifics. I'm not sure if you could mutate a local with reflection. You can easily access the current instances (or any instances) fields by a string name though. – Servy Jan 03 '14 at 16:50
  • @Servy yeah maybe you right, we can create variable names dynamically and then access fields of current assembly in runtime.Actually it worth a try :D – Selman Genç Jan 03 '14 at 16:55
  • As I said, it's almost certainly not the proper approach to this problem, and I would consider an answer along those lines to be actively harmful, however it is incorrect to say that doing so is impossible, because it most certainly is not, it's just *undesirable*. – Servy Jan 03 '14 at 16:56
  • Unfortunately it says "System.Windows.Forms.Control does not contain a definition for 'Value' and no extension method 'Value' accepting a first argument of type 'System.Windows.Forms.Control' could be found" – Vantalk Jan 03 '14 at 17:00
  • @Vantalk could you provide your code? what is the type of your control you are trying to access? – Selman Genç Jan 03 '14 at 17:02
  • It's simply a bunch of progress bars named: "ClassRoom1", "ClassRoom2".. about 15 of them. I need to take some values from a database and assign them to each. – Vantalk Jan 03 '14 at 17:06
  • I understand, then it should work. make sure your control names are correct – Selman Genç Jan 03 '14 at 17:09
1

If you want to have names for your objects, use a dictionary:

Dictionary<string, type> myDict = new Dictionary<string, type>()
string naming = "MyPattern{0}";
for (int i = 0; i <value; i++) {
    myDict.add(string.Format(naming, i.ToString()), assign[i]);
}

And then you can access them by doing, for example:

myDict["MyPattern1"]

However, I suggest you would be better off using a collection like a List or array.

NWard
  • 2,016
  • 2
  • 20
  • 24
1

Arrays, lists, dictionaries, hash maps... collections in general are what you would use here. For example, if you have a dictionary, then it consists of key/value pairs. So a dictionary might look like this:

var variable = new Dictionary<int, string>();

Where the int is the key for any given entry, and the string is the value. You'd assign values in something like this:

for(int i = 0; i < value; i++)
    variable.Add(i, assign[i]);

Of course, since i is just an incrementing integer in this case (unless you have some other key in mind?), then it works just as well as an indexer on a list. Something like this:

var variable = new List<string>();
for (int i = 0; i < value; i++)
    variable.Add(assign[i]);

In both cases, you'd access the assigned value later by referencing its key (in a dictionary) or its index (in a list, or any array):

var someOtherVariable = variable[x];

Where x is an integer value present in the dictionary's keys or in the array's size.

David
  • 208,112
  • 36
  • 198
  • 279
0

If you can put names of all variables in an array such as 'variable', and they are unique, you can try to use dictionary :

    Dictionary<object, object> dictionary = new Dictionary<string, object>();
    for(int i=0; i<value; i++)
    {
         dictionary.Add(variable[i], assign[i]);
    }
skolte
  • 367
  • 2
  • 9