Question

I'm trying to create a list that contains methods, and after I add some methods I want to execute them, is this possible?

I tried something like this:

List<object> methods = new List<object>();

Then:

methods.Add(Move());

But When I add, the program will call the methods, for example, in this case it called for Move();

Was it helpful?

Solution

This is a great use case for the Action generic delegate.

List<Action> functions = new List<Action>();
functions.Add(Move);

foreach (Action func in functions)
   func();

If you need parameters, I would use lambdas to abstract them away:

List<Action> functions = new List<Action>();
functions.Add(Move);
functions.Add(() => MoveTo(1, 5));

foreach (Action func in functions)
   func();

A delegate is akin to function pointers from C++, it holds what a function "is" (not a return value like in your example) so you can call it just like a regular function. The Action generic delegate takes no parameters and returns nothing, so it is ideal for generic "call these functions".

MSDN for Action: Action Delegate

For more on the different types of delegates provided by.NET: https://stackoverflow.com/a/567223/1783619

OTHER TIPS

I'm not sure if this outside the scope of the original question (or will help anyone else), but I kept coming back to this page in my own search of how to create a list of return-type functions to iterate and execute. I ended up using the List<Func<T>> to create a list of type methods-

        bool RTrue()
        {
            Console.WriteLine("RETURNS TRUE");
            return true;
        }

        bool RFalse()
        {
            Console.WriteLine("RETURNS FALSE");
            return false;
        }

        List<Func<Boolean>> functions = new List<Func<Boolean>>();
        functions.Add(RTrue);
        functions.Add(RFalse);

        foreach (Func<Boolean> func in functions)
        {
            if (func() == true)
            {
                Console.WriteLine("IT WORKS");
            }
        }

Further info on Func usage- What is Func, how and when is it used

You can use delegates. Create a list of delegates. Then, for each method you want to add to the list, create a delegate and add to the list.

 List<Delegate> methods = new List<Delegate>();

 // creates an Action delegate implicitly
 methods.Add((Action)Move);

Depending on what parameters are required:

var Actions = new List<Action<object, EventArgs>>
{
    ReconfirmOrderlines_Click,
    ModifyOrderlines_Click
};

Or, for example, when you want to create a list to use for dynamiclly adding items in a ContextMenuStrip with the text and Click event:

var actions = new List<(string, Action<object, EventArgs>)>
{
    ("Send confirmation", ReconfirmOrderlines_Click),
    ("Send modification", ModifyOrderlines_Click),
};

If you want to know what you need to enter inside of the list, I always use this 'trick': Trick to get the parameters

Great solution from @BradleyDotNET and @HunterTheGatherer. However I had a third requirement and that was being able to tell which method had been called in case something failed.

This is my solution for uploads to Amazon S3 sending in parameters, reading the return value and showing what method failed if any method returns false.

var uploadFunctions = new List<Expression<Func<bool>>>();
uploadFunctions.Add(() => awsS3Service.UploadOrganisationJson(organisationJson, migrationId, orgId));
uploadFunctions.Add(() => awsS3Service.UploadUsersJson(usersJson, migrationId, orgId));
uploadFunctions.Add(() => awsS3Service.UploadContactPersonJson(contactPersonJson, migrationId, orgId));

foreach (var uploadFunction in uploadFunctions)
{
    var methodCall = uploadFunction.Body as MethodCallExpression;
    var methodName = "";
    if (methodCall != null)
    {
        //methodName will be "awsS3Service.UploadOrganisationJson" for the first item
        methodName = $"{methodCall.Method.DeclaringType?.Name}.{methodCall.Method.Name}";
    }
    var func = uploadFunction.Compile();
    var success = func();
    if (!success)
    {
        SetErrorStatus(migration, customerMigration, $"Could not upload data for {methodName}");
    }
}

Source for Expression:

https://stackoverflow.com/a/20420544/3850405

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top