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 tha
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.
All languages that run on top of 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.
A delegate represents a pointer to a method. 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);
}
The type–unsafe way
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 definition.
The custom way
Besides the Delegate special class, the delegate concept spreads to custom delegates, which are declarations of methods preceded by the delegate keyword. They are thereby type–checked the same as method declarations, so you'll come up with 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 wraps up a void method with one parameter of type T1.Action wraps up a void method with two parameters of types T1 and T2, respectively.Func wraps up a parameterless function with TR return type.
Func wraps up a function with TR return type and with one parameter of type T1.
Func 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 this, parameter names don't describe what they have to be passed in, nor is the delegate name meaningful on what it's supposed to do. Therefore, be cautions about when to use these delegates and refrain from using them in contexts where their purpose is not perfectly self–evident.
The latter solution is the one most people posted. I'm still mentioning it in my answer for completeness.
- 热议问题