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.
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);
}
}
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.
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"));
In order to provide a clear and complete answer, I'm going to start from the very beginning before showing three possible solutions.
A brief introduction
All .NET languages (such as C#, F#, and Visual Basic) run on top of the Common Language Runtime (CLR), which is a VM that runs code in the Common Intermediate Language (CIL), which is way higher level than machine code. It follows that methods aren't Assembly subroutines, nor are they values, unlike functional languages and JavaScript; rather, they're symbols that CLR recognizes. Not being values, they cannot be passed as a parameter. That's why there's a special tool in .NET. That is, delegates.
What's a delegate?
A delegate represents a handle to a method (the term handle is to be preferred over pointer as the latter would be an implementation detail). Since a method is not a value, there has to be a special class in .NET, namely Delegate, which wraps up any method. What makes it special is that, like very few classes, it needs to be implemented by the CLR itself and couldn't be simply written as a class in a .NET language.
Three different solutions, the same underlying concept
The type–unsafe way
Using the Delegate special class directly.
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 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 way as “normal” method invocations, making for type-safe code.
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 stick with 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 by using predefined delegates like these, parameter names won't be self-describing, nor is the name of the delegate type meaningful as to what instances are supposed to do. Therefore, 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 also mentioning it in my answer for the sake of completeness.
The solution involves Delegates, which are used to store methods to call. Define a method taking a delegate as an argument,
public static T Runner<T>(Func<T> funcToRun)
{
// Do stuff before running function as normal
return funcToRun();
}
Then pass the delegate on the call site:
var returnValue = Runner(() => GetUser(99));
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);
}
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.
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;
}
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 it as a parameter");
}
If the method passed needs to take one argument and return a value, Func is the best way to go. Here is an example.
public int Method1(string)
{
// Do something
return 6;
}
public int Method2(string)
{
// Do something different
return 5;
}
public bool RunTheMethod(Func<string, int> myMethodName)
{
// Do stuff
int i = myMethodName("My String");
Console.WriteLine(i); // This is just in place of the "Do more stuff"
return true;
}
public bool Test()
{
return RunTheMethod(Method1);
}
Read the docs here
However, if your method that is passed as a parameter does not return anything, you can also use Action. It supports up to 16 paramaters for the passed method. Here is an example.
public int MethodToBeCalled(string name, int age)
{
Console.WriteLine(name + "'s age is" + age);
}
public bool RunTheMethod(Action<string, int> myMethodName)
{
// Do stuff
myMethodName("bob", 32); // Expected output: "bob's age is 32"
return true;
}
public bool Test()
{
return RunTheMethod(MethodToBeCalled);
}
Read the documentation here
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
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);
}
}
I don't know who might need this, but in case you're unsure how to send a lambda with a delegate, when the function using the delegate doesn't need to insert any params in there you just need the return value.
SO you can also do this:
public int DoStuff(string stuff)
{
Console.WriteLine(stuff);
}
public static bool MethodWithDelegate(Func<int> delegate)
{
///do stuff
int i = delegate();
return i!=0;
}
public static void Main(String[] args)
{
var answer = MethodWithDelegate(()=> DoStuff("On This random string that the MethodWithDelegate doesn't know about."));
}
I'm working with a project for thesis-work for a company and I'm having some difficulties understanding some code.
In their code they have a line like this
_subscriber.StartSubscribing(_messageHandler.HandleMessage);
where _subscriber is function is defined
public override void StartSubscribing(Action<QueueItem> messageHandlerMethod);
And _messageHandler is defined
public void HandleMessage(QueueItem message)
{
//Do code here
}
How come at the top the messageHandler don't need a parameter for HandleMessage?
E.I
_subscriber.StartSubscribing(_messageHandler.HandleMessage(QueueItem));
Because you're not actually executing the method HandleMessage (which would happen if you had parentheses and a parameter). You are passing it as a reference to StartSubscribing which expects a method with a specified signature (void return, one parameter of type QueueItem)
Action<T> is a generic delegate, this particular version is a delegate which specifies no return (void) and a single parameter of type T (or QueueItem in your example)
In fact, it is the method StartSubscribing (or perhaps the class it belongs to) which is likely to provide the instance of QueueItem - perhaps something like this:
public override void StartSubscribing(Action<QueueItem> messageHandlerMethod)
{
// do something to get/create a QueueItem
QueueItem item = SomeMagic();
// pass it back to the passed in delegate
messageHandlerMethod(item);
}
With _subscriber.StartSubscribing(_messageHandler.HandleMessage) you are using a more direct way for _subscriber.StartSubscribing(msg => _messageHandler.HandleMessage(msg)).
So it does need a parameter.
I'm looking for way to call Methods with Parameters using a Function Delegate.
You could use the function delegate in the place instead of calling processOperationB. but looking for any way that the below way can be achieved.
public class Client
{
public AOutput OperationA (string param1, string param2)
{
//Some Operation
}
public BOutput OperationB(string param1, string param2)
{
//Some Operation
}
}
public class Manager
{
private Client cl;
public Manager()
{
cl=new Client();
}
private void processOperationA(string param1, string param2)
{
var res = cl.OperationA(param1,param2);
//...
}
private void processOperationB(string param1, string param2)
{
var res = cl.OperationB(param1,param2);
// trying to Call using the GetData , in that case I could get rid of individual menthods for processOperationA, processOperationB
var res= GetData<BOutput>( x=> x.OperationB(param1,param2));
}
// It could have been done using Action, but it should return a value
private T GetData<T>(Func<Client,T> delegateMethod)
{
// how a Function delegate with params can be invoked
// Compiler expects the arguments to be passed here. But have already passed all params .
delegateMethod();
}
}
Your comment reads:
Compiler expects the arguments to be passed here
But that's not really true. Yes, it expects an argument, but not what you think it expects.
Your delegateMethod parameter is a Func<Client, T>, which means it requires a single argument, of type Client, and returns a value of type T. Based on the code you've shown, you should write this instead:
private T GetData<T>(Func<Client,T> delegateMethod)
{
return delegateMethod(cl);
}
It is not clear to me what broader problem you're trying to solve is. I don't see the GetData<T>() method adding anything here; the callers could just call the appropriate "Operation..." method in each case, I'd think (i.e. as in your processOperationA() method).
But at least we can solve the compiler error. If you'd like help with that broader problem, you can post a new question. Make sure to include a good Minimal, Verifiable, and Complete code example that shows clearly what you're trying to do, and explain precisely what you've tried and what's not working.
I am new to C# and still understanding the concept of delegates. What I know of delegates is that delegates define a function signature and functions with the same signature can be added to that delegate.
public class ss
{
public delegate void sampleDelegate();
public ss()
{
sampleDelegate s1 = new sampleDelegate(sampleMethod);
s1+= new sampleDelegate(sampleMethod2);
s1();
}
public static void sampleMethod()
{
}
public static void sampleMethod2()
{
}
}
In the above code I create a delegate and give it sampleMethod and sampleMethod2. When I call s1() it calls both sampleMethod() and sampleMethod2().
What if I want to only call one of those methods and that decision is to be made at runtime?
I may be missing something very small but delegates are really confusing to understand.
What if i want to only call one of those methods and that decision is to be made at runtime?
Then you don't combine them together, basically. For example:
// Names changed to be more conventional
SampleDelegate s1 = someCondition
? new SampleDelegate(SampleMethod)
: new SampleDelegate(SampleMethod2);
// This will call either SampleMethod or SampleMethod2, depending on condition
s1();
Note that normally I'd use a method group conversion, but you can't use method groups for the second and third operands of the conditional operator. You could use:
SampleDelegate s1;
if (condition) {
s1 = SampleMethod;
} else {
s2 = SampleMethod2;
}
... or
SampleDelegate s1 = someCondition
? new SampleDelegate(SampleMethod)
: SampleMethod2;
Neither of these looks particularly nice to me though.
Delegates are like pointers to a method. At run-time, there's nothing that differentiates calling a delegate or a method excluding that a method is a member of an object:
some.Method();
someDelegate();
The goal of delegates is creating a blackbox where you expect some code to put some behavior, and you simply rely on a method signature.
At the end of the day, they're like method interfaces:
// It must be a parameterless method which returns no value
public delegate void Action();
// vs
// It must be a class which implements a parameterless method "Do"
// which returns no value
public interface Action
{
void Do();
}
That is, a method can't be conditionally be switched with other, but you need to use regular control flow blocks like if or switch to take decisions about what to do.
In order to don't duplicate Jon Skeet's answer, I'll add another possible solution:
string text = "";
sampleDelegate s1 = () =>
{
if(!string.IsNullOrEmpty(text))
{
SampleMethod1();
}
else
{
SampleMethod2();
}
};
s1();
Check that, instead of creating two instances of sampleDelegate you can create one that handles the conditional logic to either call SampleMethod1 or SampleMethod2.
The whole () => { } thing is called anonymous delegate.
It can be also expressed as follows:
string text = "";
sampleDelegate s1 = delegate()
{
if(!string.IsNullOrEmpty(text))
{
SampleMethod1();
}
else
{
SampleMethod2();
}
};
But don't use above syntax... It comes from the old .NET days (.NET 1.0/1.1/2.0).
In summary, a delegate could or could not be provided as an actual class method, but you can combine class methods with anonymous delegates to meet your needs.
What if i want to only call one of those methods and that decision is
to be made at runtime? I may be missing something very small but
delegates are really confusing to understand.
Actually this is the reason to use delegates, but you're right when you say you're missing something.
Delegates are used to situations like the following one:
public void DoStuff(string text, Func<string, string> textFormatter = null)
{
Console.WriteLine(textFormatter != null ? textFormatter(text) : text);
}
You might call DoStuff either this way DoStuff("hello world") or DoStuff("hello world", text => $"<strong>{text}</strong>").
DoStuff method implementation doesn't know how to format the given text, and you provide an optional parameter to give a delegate as argument that will receive the whole text to format and it will return the formatted text.
Isn't this some way conditional after all? Based on the caller, DoStuff formats the text in a custom way. You can even provide a default format:
public void DoStuff(string text, Func<string, string> textFormatter = null)
{
// We'll give a default formatter if none is provided ;)
if(textFormatter == null)
textFormatter = text => $"<span>{text}</span>";
Console.WriteLine(textFormatter(text));
}
We have a system where we need to dynamically change what happens at the end of a set of steps.
We're doing this using a delegate. However the methods that we need to call at the end of the set of steps have different signatures.
We have a choice at the moment to either do this using a standard delegate signature (probably copying the event handler one from ASP.Net) or doing it some other way (undertermined!)
Is there a way to do this with delegates in .Net 3.5 ? Or could we do this using C# 4.0's named parameters or optional parameters on the delegate?
Your question is quite general. However, I think you could use some general delegate type and then just wrap the call to the final method into a simple lambda expression to convert the parameters appropriately.
For example, let's say that you have an event that fires with two strings as an argument. This may be created using the Action<string, string> delegate from .NET 3.5. Then you'll have two methods that you want to call (and you need to choose between them dynamically):
void Foo(int n, string s) { /* expects int as the first parameter */ }
void Bar(string concatenated) { /* expects concatenated string */ }
Then you can create two action delegates like this:
// Converts parameter to int and calls 'Foo'
Action<string, string> callFoo = (s1, s2) => Foo(Int32.Parse(s1), s2);
// Concatenates parameters and calls 'Bar'
Action<string, string> callBar = (s1, s2) => Bar(s1 + ", " + s2);
The code in lambda expressions serves as a simple adapter that converts the actual parameters to the parameters expected by the method. Now you can dynamically add/remove callFoo and callBar as handlers to the event that you want to handle.
For "normal" methods, you can pass in an open array of parameters, for example:
public void Test(params string[] string parameters);
You could use an open array of Objects. I don't know if this would work for delegates as well and also, you'd lose type safety.
You might create "state objects" that contain different properties with parameters for each invoked method and the method would only take one parameter.
public class StateObject1
{
public string parameter1;
public int parameter2;
}
public class StateObject2
{
public DateTime parameter1;
public DateTime parameter2;
}
public void Handler1(object stateObject)
{
if (!(stateObject is StateObject1))
throw new ArgumentException("Invalid state object type");
...
}
public void Handler2(object stateObject)
{
if (!(stateObject is StateObject2))
throw new ArgumentException("Invalid state object type");
...
}
We got around this by using the event handler method signature, i.e. our delegate expects (object sender, eventargs e) and we built a custom event args class.