0

I have a program that will need to run different methods depending on what I want it to talk to, and I want to know if there is a way to store some sort of method pointer or something of that sort in an array. So I want an array where each element would be something like this:

[Boolean: Do_this?] [Function_pointer] [Data to pass to the function]

So basically, I can put this into a for loop and not call each function individually. Another block of code would fill in the Boolean of whether to run this function or not, and then my for loop would go through and run the function with its appropriate data if the Boolean is true.

I know delegates are similar to function pointers, but if that is the answer here, I'm not entirely sure how I would construct what I want to construct.

Is this possible in C#?

5 Answers 5

3

Sure is, although, to do it this way, you need all methods to have the same signature:

Lets say you had two methods:

public int Moop(string s){ return 1; }
public int Moop2(string s){ return 2; }

You could do:

var funcs = new Func<string, int>[]{ Moop, Moop2 };

And to call:

var val = funcs[0]("hello");
Sign up to request clarification or add additional context in comments.

Comments

2

You could declare a specific object type to hold in a delegate, a flag that indicates whether to do that or now and the data. Note that what you are describing is very similar to events as they are also defined by a callback and some event data.

The skeletal model would look something like this, assuming all methods you want to call have the same signature (you can work around that, if you need a whole bunch of various signatures by using reflection):

// This reflects the signature of the methods you want to call
delegate void theFunction(ActionData data);

class ActionData
{
    // put whatever data you would want to pass
    // to the functions in this wrapper
}

class Action
{
    public Action(theFunction action, ActionData data, bool doIt)
    {
        this.action = action;
        this.data = data;
        this.doIt = doIt;
    }

    public bool doIt
    {
        get;
        set;
    }

    public ActionData data
    {
        get;
        set;
    }

    public theFunction action
    {
        get;
        set;
    }

    public void run()
    {
        if (doIt)
            action(data);
    }
}

And a regular use case would look something like this:

class Program
{
    static void someMethod(ActionData data)
    {
        Console.WriteLine("SUP");
    }

    static void Main(string[] args)
    {
        Action[] actions = new Action[] {
            new Action(Program.someMethod, new ActionData(), true)
        };

        foreach(Action a in actions) 
            a.run();
    }
}

4 Comments

While this option is rather long, I decided to use this one because it is incredibly readable and should do exactly what I needed. Thank you for the assistance. The other answers were good as well, but I think this one will help the most in the long run.
Yes, I agree it's got sort of a Java-verbosity feeling inside, but I felt like this approach was a tad clearer than the templated array approach. Also, you should check out @Servy's response, as it seems to provide a slightly cleaner alternative (albeit lacking the enabled flag).
@AndreiBârsan I did address having an 'enabled' flag in comments. It's easy enough to not actually add the method if it shouldn't exist, add a no-op action, or have the method itself check, whatever, before executing some block of code.
Ah, yes, upon re-reading your question I realized this! Well, I'm happy this part of my answer didn't get in your way. :)
1

Yes, you can.

If all your functions share the same signature you might want to store delegates in your collection, otherwise I would go for System.Reflection.MethodInfo, which you can use later on by calling Invoke method. Parameters would be stored as array of objects - that's what Invoke expects.

If using reflection is too slow you can use Reflection.Emit to generate dynamic methods at runtime.

Comments

1

I would just create a List<Action>. Action is a delegate that takes no parameters and returns no results. You can use currying and lambdas such that the actual actions can call a method that has parameters. In the case where you don't actually want to run it, just don't add it to the list in the first place (or add an action that does nothing I guess).

To add an item it might look something like:

list.Add(() => someobject.someMethod(firstArgument, secondArgument));
list.Add(() => anotherObject.anotherMethod(oneArgument));

Then you can just run all of the actions when you want to:

foreach(Action action in list)
{
  action();
}

Comments

0

This is exactly what you would use delegates for. Delegates are, more or less, type-checked function pointers. You can create some delegates and put them into an array.

Func<int, int> [] funcs = new Func<int,int>[] { x => 2 * x, x => x * x };
foreach(var fn in funcs) 
{
    Console.WriteLine(fn(3));
    Console.WriteLine(fn(8));
}

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.