[c#] Pass Method as Parameter using C#

I have several methods all with the same parameter types and return values but different names and blocks. I want to pass the name of the method to run to another method that will invoke the passed method.

public int Method1(string)
{
    // Do something
    return myInt;
}

public int Method2(string)
{
    // Do something different
    return myInt;
}

public bool RunTheMethod([Method Name passed in here] myMethodName)
{
    // Do stuff
    int i = myMethodName("My String");
    // Do more stuff
    return true;
}

public bool Test()
{
    return RunTheMethod(Method1);
}

This code does not work but this is what I am trying to do. What I don't understand is how to write the RunTheMethod code since I need to define the parameter.

This question is related to c# .net methods delegates

The answer is


While the accepted answer is absolutely correct, I would like to provide an additional method.

I ended up here after doing my own searching for a solution to a similar question. I am building a plugin driven framework, and as part of it I wanted people to be able to add menu items to the applications menu to a generic list without exposing an actual Menu object because the framework may deploy on other platforms that don't have Menu UI objects. Adding general info about the menu is easy enough, but allowing the plugin developer enough liberty to create the callback for when the menu is clicked was proving to be a pain. Until it dawned on me that I was trying to re-invent the wheel and normal menus call and trigger the callback from events!

So the solution, as simple as it sounds once you realize it, eluded me until now.

Just create separate classes for each of your current methods, inherited from a base if you must, and just add an event handler to each.


public static T Runner<T>(Func<T> funcToRun)
{
    //Do stuff before running function as normal
    return funcToRun();
}

Usage:

var ReturnValue = Runner(() => GetUser(99));

You need to use a delegate. In this case all your methods take a string parameter and return an int - this is most simply represented by the Func<string, int> delegate1. So your code can become correct with as simple a change as this:

public bool RunTheMethod(Func<string, int> myMethodName)
{
    // ... do stuff
    int i = myMethodName("My String");
    // ... do more stuff
    return true;
}

Delegates have a lot more power than this, admittedly. For example, with C# you can create a delegate from a lambda expression, so you could invoke your method this way:

RunTheMethod(x => x.Length);

That will create an anonymous function like this:

// The <> in the name make it "unspeakable" - you can't refer to this method directly
// in your own code.
private static int <>_HiddenMethod_<>(string x)
{
    return x.Length;
}

and then pass that delegate to the RunTheMethod method.

You can use delegates for event subscriptions, asynchronous execution, callbacks - all kinds of things. It's well worth reading up on them, particularly if you want to use LINQ. I have an article which is mostly about the differences between delegates and events, but you may find it useful anyway.


1 This is just based on the generic Func<T, TResult> delegate type in the framework; you could easily declare your own:

public delegate int MyDelegateType(string value)

and then make the parameter be of type MyDelegateType instead.


In order to provide a clear and complete answer, I'm going to start from the very beginning before coming up with three possible solutions.


A brief introduction

All languages that run on top of the CLR (Common Language Runtime), such as C#, F#, and Visual Basic, work under a VM that runs higher level code than machine code, which native languages like C and C++ are compiled to. It follows that methods aren't Assembly subroutines, nor are they values, unlike JavaScript as well as most functional languages; rather, they're definitions that CLR recognizes. Thus, you cannot think to pass a method as a parameter, because methods don't produce any values themselves, as they're not expressions but statements, which are stored in the generated assemblies. At this point, you'll face delegates.


What's a delegate?

A delegate represents a handle to a method (the term handle is to be preferred over pointer as it is implementation–dependent.) As I said above, a method is not a value, hence there's a special class in CLR languages, namely Delegate, which wraps up any method.

Look at the following example:

static void MyMethod()
{
    Console.WriteLine("I was called by the Delegate special class!");
}

static void CallAnyMethod(Delegate yourMethod)
{
    yourMethod.DynamicInvoke(new object[] { /*Array of arguments to pass*/ });
}

static void Main()
{
    CallAnyMethod(MyMethod);
}

Three different solutions, the same underlying concept:

  • The type–unsafe way
    Using the Delegate special class directly the same way as the example above. The drawback here is your code being type–unsafe, allowing arguments to be passed dynamically, with no constraints.

  • The custom way
    Besides the Delegate special class, the concept of delegates spreads to custom delegates, which are declarations of methods preceded by the delegate keyword. They are type–checked the same as method declarations, leading to flawlessly safe code.

    Here's an example:

    delegate void PrintDelegate(string prompt);
    
    static void PrintSomewhere(PrintDelegate print, string prompt)
    {
        print(prompt);
    }
    
    static void PrintOnConsole(string prompt)
    {
        Console.WriteLine(prompt);
    }
    
    static void PrintOnScreen(string prompt)
    {
        MessageBox.Show(prompt);
    }
    
    static void Main()
    {
        PrintSomewhere(PrintOnConsole, "Press a key to get a message");
        Console.Read();
        PrintSomewhere(PrintOnScreen, "Hello world");
    }
    
  • The standard library's way
    Alternatively, you can use a delegate that's part of the .NET Standard:

    • Action wraps up a parameterless void method.
    • Action<T1> wraps up a void method with one parameter of type T1.
    • Action<T1, T2> wraps up a void method with two parameters of types T1 and T2, respectively.
    • And so forth...
    • Func<TR> wraps up a parameterless function with TR return type.
    • Func<T1, TR> wraps up a function with TR return type and with one parameter of type T1.
    • Func<T1, T2, TR> wraps up a function with TR return type and with two parameters of types T1 and T2, respectively.
    • And so forth...

    However, bear in mind that using predefined delegates like these, parameter names won't describe what they have to be passed in, nor is the delegate name meaningful on what it's supposed to do. Therefore, be cautious about when to use these delegates and refrain from using them in contexts where their purpose is not absolutely self–evident.

The latter solution is the one most people posted. I'm still mentioning it in my answer for the sake of completeness.


Here is an example without a parameter: http://en.csharp-online.net/CSharp_FAQ:_How_call_a_method_using_a_name_string

with params: http://www.daniweb.com/forums/thread98148.html#

you basically pass in an array of objects along with name of method. you then use both with the Invoke method.

params Object[] parameters


If you want to pass Method as parameter, use:

using System;

public void Method1()
{
    CallingMethod(CalledMethod);
}

public void CallingMethod(Action method)
{
    method();   // This will call the method that has been passed as parameter
}

public void CalledMethod()
{
    Console.WriteLine("This method is called by passing parameter");
}

Here is an example Which can help you better to understand how to pass a function as a parameter.

Suppose you have Parent page and you want to open a child popup window. In the parent page there is a textbox that should be filled basing on child popup textbox.

Here you need to create a delegate.

Parent.cs // declaration of delegates public delegate void FillName(String FirstName);

Now create a function which will fill your textbox and function should map delegates

//parameters
public void Getname(String ThisName)
{
     txtname.Text=ThisName;
}

Now on button click you need to open a Child popup window.

  private void button1_Click(object sender, RoutedEventArgs e)
  {
        ChildPopUp p = new ChildPopUp (Getname) //pass function name in its constructor

         p.Show();

    }

IN ChildPopUp constructor you need to create parameter of 'delegate type' of parent //page

ChildPopUp.cs

    public  Parent.FillName obj;
    public PopUp(Parent.FillName objTMP)//parameter as deligate type
    {
        obj = objTMP;
        InitializeComponent();
    }



   private void OKButton_Click(object sender, RoutedEventArgs e)
    {


        obj(txtFirstName.Text); 
        // Getname() function will call automatically here
        this.DialogResult = true;
    }

class PersonDB
{
  string[] list = { "John", "Sam", "Dave" };
  public void Process(ProcessPersonDelegate f)
  {
    foreach(string s in list) f(s);
  }
}

The second class is Client, which will use the storage class. It has a Main method that creates an instance of PersonDB, and it calls that object’s Process method with a method that is defined in the Client class.

class Client
{
  static void Main()
  {
    PersonDB p = new PersonDB();
    p.Process(PrintName);
  }
  static void PrintName(string name)
  {
    System.Console.WriteLine(name);
  }
}

From OP's example:

 public static int Method1(string mystring)
 {
      return 1;
 }

 public static int Method2(string mystring)
 {
     return 2;
 }

You can try Action Delegate! And then call your method using

 public bool RunTheMethod(Action myMethodName)
 {
      myMethodName();   // note: the return value got discarded
      return true;
 }

RunTheMethod(() => Method1("MyString1"));

Or

public static object InvokeMethod(Delegate method, params object[] args)
{
     return method.DynamicInvoke(args);
}

Then simply call method

Console.WriteLine(InvokeMethod(new Func<string,int>(Method1), "MyString1"));

Console.WriteLine(InvokeMethod(new Func<string, int>(Method2), "MyString2"));

If you want the ability to change which method is called at run time I would recommend using a delegate: http://www.codeproject.com/KB/cs/delegates_step1.aspx

It will allow you to create an object to store the method to call and you can pass that to your other methods when it's needed.


You should use a Func<string, int> delegate, that represents a function taking a string argument and returning an int value:

public bool RunTheMethod(Func<string, int> myMethod)
{
    // Do stuff
    myMethod.Invoke("My String");
    // Do stuff
    return true;
}

Then invoke it this way:

public bool Test()
{
    return RunTheMethod(Method1);
}

Examples related to c#

How can I convert this one line of ActionScript to C#? Microsoft Advertising SDK doesn't deliverer ads How to use a global array in C#? How to correctly write async method? C# - insert values from file into two arrays Uploading into folder in FTP? Are these methods thread safe? dotnet ef not found in .NET Core 3 HTTP Error 500.30 - ANCM In-Process Start Failure Best way to "push" into C# array

Examples related to .net

You must add a reference to assembly 'netstandard, Version=2.0.0.0 How to use Bootstrap 4 in ASP.NET Core No authenticationScheme was specified, and there was no DefaultChallengeScheme found with default authentification and custom authorization .net Core 2.0 - Package was restored using .NetFramework 4.6.1 instead of target framework .netCore 2.0. The package may not be fully compatible Update .NET web service to use TLS 1.2 EF Core add-migration Build Failed What is the difference between .NET Core and .NET Standard Class Library project types? Visual Studio 2017 - Could not load file or assembly 'System.Runtime, Version=4.1.0.0' or one of its dependencies Nuget connection attempt failed "Unable to load the service index for source" Token based authentication in Web API without any user interface

Examples related to methods

String method cannot be found in a main class method Calling another method java GUI ReactJS - Call One Component Method From Another Component multiple conditions for JavaScript .includes() method java, get set methods includes() not working in all browsers Python safe method to get value of nested dictionary Calling one method from another within same class in Python TypeError: method() takes 1 positional argument but 2 were given Android ListView with onClick items

Examples related to delegates

Delegates in swift? How can I make a weak protocol reference in 'pure' Swift (without @objc) C# cannot convert method to non delegate type Invoke(Delegate) What is a C++ delegate? How do I set up a simple delegate to communicate between two view controllers? LINQ where clause with lambda expression having OR clauses and null values returning incomplete results C# - using List<T>.Find() with custom objects Func vs. Action vs. Predicate What is Func, how and when is it used