Pass Method as Parameter using C#

2018-12-31 06:51发布

I have several methods all with the same signature (parameters and return values) but different names and the internals of the methods are different. I want to pass the name of the method to run to another method that will invoke the passed in 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.

10条回答
只靠听说
2楼-- · 2018-12-31 07:38

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

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

Then use it:

public bool Test() {
    return RunTheMethod(Method1);
}
查看更多
ら面具成の殇う
3楼-- · 2018-12-31 07:44

For sharing a as complete as possible solution, I'm going to end up with presenting three different ways of doing, but now I'm going to start from the most basic principle.


Brief introduction

All CLR (Common Language Runtime) languages (such as C# and Visual Basic) work under a VM called CLI (Common Language Interpreter) which runs the code on a higher level than native languages like C and C++ (which directly compile to machine code). It follows that methods aren't any kind of compiled block, but they are just structured elements which CLR recognize and use to pull out their body and rewing it to the inline instructions of the machine code. Thus, you cannot think to pass a method as a parameter, because a method doesn't produce any value by itself: it's not a valid expression! So that, you are going to stumble the delegate concept.


What's a delegate?

A delegate represents a pointer to a method. Because of (as I said above) a method is not a value, there's a special class in CLR languages: Delegate. That class wraps any method and you can implicitly cast any method to that.

Look at the following usage 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);
}

The three ways:

  • Way 1
    Use the Delegate special class directly as the example above. The problem of this solution is that your code will be unchecked as you pass dynamically your arguments without restricting them to the types of those in the method declaration.

  • Way 2/3 Besides the Delegate special class, the delegates concept spreads to custom delegates, which are declarations of methods preceeded by the delegate keyword and they behave like a normal method. They are so checked, and you'll come up to a "perfect" code.

Look at the following 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");
}

A second option by this way not to write your own custom delegate is using one of them declared within system libraries:

  • Action wraps a void with no arguments.
  • Action<T1> wraps a void with one argument.
  • Action<T1, T2> wraps a void with two arguments.
  • And so on...
  • Func<TR> wraps a function with TR return type and with no arguments.
  • Func<TR, T1> wraps a function with TR return type and with one argument.
  • Func<TR, T1, T2> wraps a function with TR return type and with two arguments.
  • And so on...

(This latter solution is that many people posted.)

查看更多
姐姐魅力值爆表
4楼-- · 2018-12-31 07:48

You can use the Func delegate in .net 3.5 as the parameter in your RunTheMethod method. The Func delegate allows you to specify a method that takes a number of parameters of a specific type and returns a single argument of a specific type. Here is an example that should work:

public class Class1
{
    public int Method1(string input)
    {
        //... do something
        return 0;
    }

    public int Method2(string input)
    {
        //... do something different
        return 1;
    }

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

    public bool Test()
    {
        return RunTheMethod(Method1);
    }
}
查看更多
浪荡孟婆
5楼-- · 2018-12-31 07:50

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

查看更多
登录 后发表回答