简体   繁体   中英

Store methods in arrays

I have an if statement in a foreach and was wondering if I can call a different method depending on what items are true without having to do a switch or if statements for all of them.

foreach (var item in buttons)
{
    if(item.isClicked)
        //call item method 
}

buttons is not of class Buttons

What I'm looking for is like
button[0] calls method start()
button[1] calls method options()

Is there any way I can do this?

You could do something like this:

private void DoStuff(params Action[] methods) {
    for (int i = 0; i < buttons.Length; i++) {
        if (buttons[i].isClicked) {
            methods[i]();
            break;
        }
    }
}

Then, you would say:

DoStuff(start, options);

Where start is the method called for the first button, options for the second, x for n .. etc.

Assuming your buttons don't support proper events , I suppose what you're looking for is a delegate . There are several ways to do this, but the most obvious thing that comes to mind is something like this:

Action[] actions = new Action[2]; // create an array of actions, with 1 action for each button
actions[0] = start;
actions[1] = options;

...

for(var i = 0; i < buttons.Length; i++)
{
    if(buttons[i].isClicked)
        actions[i]();
}

There are a couple of ways to achieve this, which way you use really depends on how much access you have to modify the class of your "buttons" (which you haven't actually told us what it is).

Option 1: Add a new member to the class (provided the class of 'buttons' is your own class)
Modify your class to have a new member, called Action or some such name. This member will be a Delegate (note: You can use a more specific type like Action<T> if you know each button's action has an identical method signature. Once you have this member declared, you can easily call it. Pseudocode:

public class MyButton {
    public bool isClicked { get; }
    public Delegate action { get; }
}

foreach (var item in buttons) {
    if(item.isClicked)
        ((Action)item.action)(); // assuming that your "action" is a method which returns nothing and takes no arguments, cast to a more appropriate type if needed
}

Option 2: Map each button to an action Similar principal to Option 1, except because you can't directly modify the backing class you'll have to bind actions to buttons after the fact. You can create a map (or Dictionary<TKey,TValue> in C#) to map the buttons to their actions. To do this, create a new Dictionary and add each button as a key alongside its action:

// Declared at class-scope 
private readonly Dictionary<MyButton,Delegate> _actions = new Dictionary<MyButton,Delegate>(); // I don't know what type 'buttons' is so I'm substituting it with "MyButton"

// In some initializer for the class (i.e the constructor)
_actions.Add(buttons[0], start)
_actions.Add(buttons[1], options)
// .. etc

// Then your loop becomes something like:
foreach(var item in buttons) {
    if (item.isClicked && _actions.ContainsKey(item)) {
        ((Action)_actions[item])();
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM