Different methods using Functors/Delegates in c# - c#

I have a method that I call multiple times, but each time a different method with a different signature is called from inside.
public void MethodOne()
{
//some stuff
*MethodCall();
//some stuff
}
So MethodOne is called multiple times, each time with a different *MethodCall(). What I'm trying to do is something like this :
public void MethodOne(Func<> MethodCall)
{
//some stuff
*MethodCall;
//some stuff
}
but the Methods that are called each have a different return type and different parameters. Is there a way to do this using Functors? If not, how would I go about doing this?
Thank you!

You best bet would be to use the non-generic Action type (or MethodInvoker would be the same), i.e.
public void MethodOne(Action callback)
{
//some stuff
if(callback != null) callback();
//some stuff
}
From this you can call any method by wrapping it at the caller, i.e.
MethodOne(SimpleMethod); // SimpleMethod has no parameters and returns void
MethodOne(() => MoreComplexMethod(1, "abc")); // this one returns void
MethodOne(() => { MethodThatReturnsSomething(12); }); // anything you like
etc

You cannot call a function which requires parameters without supplying them, so the answer is "no, not possible"
Also, maybe you want the following:
void MethodOne(Action a)
{
// some stuff
a();
// some stuff
}
... // somewhere in the code
MethodOne((Action)(() => { DoSomethingOther(1, 2, 3); }));
MethodOne((Action)(() => { DoSomethingEvenDifferent(1, 2, 3, 4, 5); }));

Every delegate in .Net is an instance of a class derived from Delegate. So if you really wish to pass 'any' delegate to a method, you can pass it as Delegate
To invoke it, you need to use its DynamicInvoke method.
public void MethodOne(Delegate MethodCall)
{
//some stuff
//Assuming you now have the required parameters
//or add params object[] args to the signature of this method
object res = MethodCall.DynamicInvoke(args); //args is object[] representing the parameters
//some stuff
}
But this is not recommended as DynamicInvoke is slow and it does not offer any compile time safety. Probably you should revisit your design.

This is basically not possible. You could make MethodOne generic for the return type, and use a lambda that closes over its outside block instead of parameters:
static void Main(string[] args)
{
int parameterSubst = 1;
int result = MethodOne<int>(() => parameterSubst);
string result2 = MethodOne<string>(() =>
{
string s = parameterSubst.ToString();
s += "foo";
return s;
});
}
static T MethodOne<T>(Func<T> function)
{
return function();
}
As you can see, parameterSubst is used in the passed Func<T>s, but not as a parameter.

Related

Passing argument to an Action without using an anonymous function?

Is there a way I can pass through an argument to an Action without using an anonymous function?
Eg, the following code works fine:
private void doSomethingAndLogIt(string log, Action dosomething)
{
Debug.WriteLine(log);
dosomething();
}
private void multiplyIt()
{
_result = "great";
}
...
doSomethingAndLogIt("Did something", multiplyIt);
but what I want to do is this:
private void doSomethingAndLogIt(string log, Action<int> dosomething)
{
Debug.WriteLine(log);
dosomething(???);
}
private void multiplyIt(int a)
{
_result = "great";
}
doSomethingAndLogIt("Did something", multiplyIt(5));
I realise that I can do this:
private void doSomethingAndLogIt(string log, Action<int> dosomething, int inputValue)
{
Debug.WriteLine(log);
dosomething(inputValue);
}
private void multiplyIt(int a)
{
_result = "great";
}
doSomethingAndLogIt("Did something", multiplyIt, 5);
but it's pretty confusing. I also realise that I can do this:
doSomethingAndLogIt("Did something", () => {
multiplyIt(5);
});
but it would be great if I could do this:
doSomethingAndLogIt("Did something", multiplyIt(5));
You do not need to do anything special. This code below:
doSomethingAndLogIt("Test", () => multiplyIt(5));
will already do what you are after. When the delegate is called, the parameter 5 will be passed in as well. Why? Because the callee will call your delegate, and you will call the method multiply with the argument 5.
Here is a quick test.
It isn't possible to do that as of the current version of C#, here's why...
Let's take your example (fake syntax)
public int MultiplyIt(int value)
{
//Do something that has side-effects
}
public void SomeMethod(Action<int> someAction<int>)
{
//Do something
someAction();
}
Now let's create an override of that method:
public void SomeMethod(int someValue)
{
//Do something
}
Now you call it:
SomeMethod(multiplyIt(5))
Which one does the compiler call?
Lets say you don't overload it (or that for some reason the compiler shouts an error if you do, but it is legal).
What then is the difference between these two calls?
SomeMethod(multiplyIt(5));
SomeMethod(() => multiplyIt(5));
Technically the first one runs multiplyIt before passing its value to SomeMethod. The second one multiplyIt may never be called, or it may alter something and then call it. That is an important distinction. If you add in some method to call it without the () => part, the developer can't know, without reading documentation, how the method call (and the action) are called. Is it a normal method call? The "special" delegate case? Who knows.
The () => isn't that much of a price to pay to be able to read a method and understand that you are passing in a delegate vs a value.

Subscribe delegates to all methods of a class

I have just familiarized myself a little bit with C# delegates. One can subscribe multiple delegate instances to a delegate by the "+=" operator. But is it also possible to have a controller class that has delegates for all the methods in second class, and have the methods being added automatically, i.e. without having to add (or even know) each method individually to the corrsponding delegate ?
In simplified code (omitting access modifiers etc.):
class Car
{
void Start();
void Drive();
}
// I would like to have the following class generated automatically
// without needing to repeat all the methods of Car, i.e.
// without declaring a delegate instance for each of them
class CarController
{
delegate void DoSomething();
DoSomething StartAll;
DoSomething DriveAll;
void Subscribe(Car anotherCar)
{
StartAll += anotherCar.Start;
DriveAll += anotherCar.Drive;
}
}
EDIT:
Rawling's solution is the one that I like best. It's simple and clear. As a little tweak I have tried how the thing would work with dynamically typed objects, and it works indeed: complete decoupling between Controller and controlled objects. Of course such usage of "dynamic" is not of everyone's taste...
public class CallAller2 : HashSet<dynamic>
{
public void CallAll(Action<dynamic> action)
{
foreach (dynamic t in this)
{
try {action(t);} catch (RuntimeBinderException) {};
}
}
}
class Bike
{
void Drive();
}
CallAller2 ca = new CallAller2();
ca.Add(new Car());
ca.Add(new Bike());
ca.CallAll(c => c.Start()); // is ignored by Bike which does not implement it
ca.CallAll(c => c.Drive());
Now I realise this is just essentially recreating the much-maligned List<T>.ForEach. Why not just use that, since it's there?
Although it doesn't give you the ability to just call .StartAll or .DriveAll, you could do something as simple as
class CallAller<T> : HashSet<T>
{
public void CallAll(Action<T> action)
{
foreach (T t in this)
{
action(t);
}
}
}
var ca = new CallAller<Car>();
ca.Add(myFirstCar);
ca.Add(mySecondCar);
// Call a simple function
ca.CallAll(c => c.Start());
// Call a function taking parameters
ca.CallAll(c => c.SetRadio(88.1, RadioType.FM));
// Get return values... if you really need to.
Dictionary<Car, int> returnValues = new Dictionary<Car, int>();
ca.CallAll(c => returnValues.Add(c, c.GetNumberOfTyres()));
If you want something with actual methods to call and Intellisense, you'll need to look into code generation - it's possible, but I doubt it'd be worth the hassle.
I think this should work:
//Edit: Don't simplify the MethodInfo mi1 = mi, otherwise you get a problem called Access to modified closure
static IList<Action> getDelegatesFromObject(Object obj)
{
Type type = obj.GetType();
List<Action> Actions = new List<Action>();
foreach (MethodInfo mi in type.GetMethods())
{
MethodInfo mi1 = mi;
Actions.Add(
() => mi1.Invoke(obj, new object[] {})
);
}
return Actions;
}

Does C# have a concept of methods inside of methods?

I have been using javascript and I made a lot of use of functions inside of functions. I tried this in C# but it seems they don't exist. If I have the following:
public abc() {
}
How can I code a method d() that can only be called
from inside the method the method abc() ?
I wouldn't worry so much about the restriction of access to a method on the method level but more class level, you can use private to restrict access of the method to that specific class.
Another alternative would be to use lambdas/anonymous methods, or if you're using C# 4.0, Action/Tasks to create them inside your method.
An example of an anonymous method using a delegate (C# 1/2/3/4) for your specific example (incl. I need an action that can take a string parameter and return a string?) would be something like this:
delegate string MyDelegate(string);
public void abc() {
// Your code..
MyDelegate d = delegate(string a) { return a + "whatever"; };
var str = d("hello");
}
.. using C# 3/4:
public void abc() {
// Your code..
Func<string, string> d = (a) => { return a + "whatever"; };
var str = d("hello");
}
.. using a more ideal solution through private method:
private string d(string a)
{
return a + "whatever";
}
public void abc()
{
// Your code..
var str = d("hello");
}
Based on your comment for another answer: I would just like to have this at the bottom of the method and then call it from some earlier code.
This won't be possible, you would need to define a variable for your method using either delegates or Actions and so it would need to be fully initialised by time you call it. You wouldn't then be able to define this at the bottom of your method. A much better option would be to simply create a new private method on your class and call that.
It is not the way to define classes, but you could do:
public abc() {
Action d = () => {
// define your method
};
d();
}
You cannot declare a method inside another method, but you can create anonymous functions inside methods:
public void abc()
{
Action d = () => { ... };
// ...
d();
}
... that can only be called from inside the method the method abc() ?
The method can only be called if you have a reference to it. If you don't store the reference elsewhere then you should be fine.
how can I pass and return a string to the action?
Use a Func instead of an Action:
Func<string, string> d = s => {
return s + "foo";
};
The reason I would like to do this is to make my code more readable.
It's good to try to make your code more readable but I think this change will make it less readable. I suggest you use ordinary methods, and not anonymous functions. You can make them private so that they cannot be called from outside your class.
Use action delegates. More effective than you did.
public abc() {
Action <int> GetInt = (i) =>
{
//Write code here
Console.Writeline("Your integer is: {0}", i);
};
GetInt(10);
}
Action is a delegate so you can give parameter as a method, not variable. Action delegate encapsulates a method that has no parameters and does not return a value. Check it from MSDN.
Yes, they are called delegates and anonymous methods.
Delegate signatures must be predefined outside of the method for the body to be assigned, so it's not exactly like a function. You would first declare a delegate:
class MyClass {
public delegate boolean Decider(string message);
/* ... */
}
And then in MyClass.MyMethod you can say Decider IsAllLowerCase = /* method name or anonymous method */; and then use it with var result = IsAllLowerCase(s);.
The good news is that .NET already has delegate definitions for most signatures you could possibly need. System.Action has assorted signatures for methods which do not return anything, and System.Func is for the ones that do.
As shown elsewhere,
Action<int, string> a = (n, s) => { for(var i=0; i<n; i++) Console.WriteLine(s);};
Allows you to call a( /* inputs */ ); as if it was a local variable. (stuff) => { code } is "lambda expression" or an anonymous method, you can also just pass a name of a method (if the signature matches):
Action<string> a = Console.WriteLine;
If you want to return something, use Func:
Func<bool, string> f = (b) => { return b.ToString(); };
Allows you to call var result = f(b); in the same way.
As a footnote, delegates are a fun part of C#/.NET but usually, the way to control access is to make another method inside your class, and declare it private. If your issue is name conflicts, then you might want to refactor. For example, you can group methods in another class declared inside your original class (nested classes are supported) or move them to another class entirely.
You can use action delegates
public abc() {
Action action = () =>
{
//Your code here
}
action();
}
Edit: To pass parameter
public abc() {
Action <string>action = (str) =>
{
//Your code here
};
}
action("hello");
Using Func to return a value
public void abc() {
Func<string, string> func = (str) => { return "You sent " + str; };
string str = func("hello");
}
You CAN create a nested class:
public class ContainingClass
{
public static class NestedClass
{
public static void Method2()
{
}
public static void Method3()
{
}
}
}
Then yu can call:
ContainingClass.NestedClass.Method2();
or
ContainingClass.NestedClass.Method3();
I wouldn't recommend this though. Usually it's a bad idea to have public nested types.

Can methods be called via an array in C#?

I have a program that will need to run different methods depending on what I want it to talk to, and I want to know if there is a way to store some sort of method pointer or something of that sort in an array. So I want an array where each element would be something like this:
[Boolean: Do_this?] [Function_pointer] [Data to pass to the function]
So basically, I can put this into a for loop and not call each function individually. Another block of code would fill in the Boolean of whether to run this function or not, and then my for loop would go through and run the function with its appropriate data if the Boolean is true.
I know delegates are similar to function pointers, but if that is the answer here, I'm not entirely sure how I would construct what I want to construct.
Is this possible in C#?
Sure is, although, to do it this way, you need all methods to have the same signature:
Lets say you had two methods:
public int Moop(string s){ return 1; }
public int Moop2(string s){ return 2; }
You could do:
var funcs = new Func<string, int>[]{ Moop, Moop2 };
And to call:
var val = funcs[0]("hello");
You could declare a specific object type to hold in a delegate, a flag that indicates whether to do that or now and the data. Note that what you are describing is very similar to events as they are also defined by a callback and some event data.
The skeletal model would look something like this, assuming all methods you want to call have the same signature (you can work around that, if you need a whole bunch of various signatures by using reflection):
// This reflects the signature of the methods you want to call
delegate void theFunction(ActionData data);
class ActionData
{
// put whatever data you would want to pass
// to the functions in this wrapper
}
class Action
{
public Action(theFunction action, ActionData data, bool doIt)
{
this.action = action;
this.data = data;
this.doIt = doIt;
}
public bool doIt
{
get;
set;
}
public ActionData data
{
get;
set;
}
public theFunction action
{
get;
set;
}
public void run()
{
if (doIt)
action(data);
}
}
And a regular use case would look something like this:
class Program
{
static void someMethod(ActionData data)
{
Console.WriteLine("SUP");
}
static void Main(string[] args)
{
Action[] actions = new Action[] {
new Action(Program.someMethod, new ActionData(), true)
};
foreach(Action a in actions)
a.run();
}
}
Yes, you can.
If all your functions share the same signature you might want to store delegates in your collection, otherwise I would go for System.Reflection.MethodInfo, which you can use later on by calling Invoke method. Parameters would be stored as array of objects - that's what Invoke expects.
If using reflection is too slow you can use Reflection.Emit to generate dynamic methods at runtime.
I would just create a List<Action>. Action is a delegate that takes no parameters and returns no results. You can use currying and lambdas such that the actual actions can call a method that has parameters. In the case where you don't actually want to run it, just don't add it to the list in the first place (or add an action that does nothing I guess).
To add an item it might look something like:
list.Add(() => someobject.someMethod(firstArgument, secondArgument));
list.Add(() => anotherObject.anotherMethod(oneArgument));
Then you can just run all of the actions when you want to:
foreach(Action action in list)
{
action();
}
This is exactly what you would use delegates for. Delegates are, more or less, type-checked function pointers. You can create some delegates and put them into an array.
Func<int, int> [] funcs = new Func<int,int>[] { x => 2 * x, x => x * x };
foreach(var fn in funcs)
{
Console.WriteLine(fn(3));
Console.WriteLine(fn(8));
}

Call/Invoke a method based on a string value contained in an array [duplicate]

This question already has answers here:
Calling a function from a string in C#
(5 answers)
Closed 1 year ago.
I have a struct-array that contains details of different reports that can be run. Each report calls a different method and currently the program has to manually check the selected report value to specifically call the appropriate method.
I would like to store the method name in the struct-array and then have program invoke that method when there is match. Is this possible?
Currently:
if (this.cboSelectReport.Text == "Daily_Unload")
{
reportDailyUnload();
}
Ideally:
if(this.cboSelectReport.Text == MyArray[i].Name)
{
something(MyArray[i].MethodName);
}
UPDATE
I tired a number of the suggestions below and none of them worked. They didn't work probably due to how I have my program structured.
You can do it using reflection, but IMO it is too fragile: it introduces an invisible dependency on the name of the method that you call.
// Assuming that the method is static, you can access it like this:
var namedReportMethod = "MyReport1";
var reportMethod = typeof(ReporterClass).GetMethod(namedReportMethod);
var res = reportMethod.Invoke(null, new object[] {reportArg1, reportArg2});
A better approach would be to define a delegate based on your method, and store it in the struct/class instead of the method name.
delegate void ReportDelegate(int param1, string param2);
class Runner {
public static void RunReport(ReportDelegate rd) {
rd(1, "hello");
}
}
class Test {
static void TestReport(int a, string b) {
// ....
}
public static void Main(string[] args) {
Runner.RunReport(TestReport);
}
}
Instead of defining your own delegate types, you can use pre-defined ones based on Action<T1,T2,...> or Func<T1,T2,R>, depending on your need to return values from the reports.
Rather than storing the method name, you could store a delegate:
struct ReportInfo
{
public string Name { get; set; }
public Action Method { get; set; }
}
//...
MyArray[0] = new ReportInfo { Name = "Daily_Unload", Action = this.reportDailyUnload };
//...
if(this.cboSelectReport.Text == MyArray[i].Name)
{
MyArray[i].Method.Invoke();
}
Most people seem to prefer the alternative syntax where you can invoke a delegate as if it were a method, using a list of arguments in parentheses. I tend to avoid this, because it can be ambiguous whether the thing being invoked is a method or a delegate:
MyArray[i].Method();
In this case, we're invoking the delegate that is referred to by the Method property, but this code could also represent a call to a method called "Method". Confusing.
As for me, supporting simple switch is much easier than dealing with reflection, array of method names or delegates, and invoking that stuff:
switch (reportType)
{
case "Daily_Unload":
ReportDailyUnload();
break;
// ...
}
If all the methods share the same signature, one way would be to cache a delegate:
// initialize, maybe in a constructor
Dictionary<string, Action> nameDelegateMapping = new Dictionary<string, Action>();
// setup the delegates
nameDelegateMapping.Add("Daily_Unload", reportDailyUnload);
// ... add more methods here.
// later
string methodName = this.cboSelectReport.Text;
Action action;
if (nameDelegateMapping.TryGetValue(methodName, out action))
{
action();
}
else
{
// tell user the method does not exist.
}
Yes, what you are talking about is reflection. Here is an article on how to invoke a method. There is a lot you can find on reflection using google.
Add a delegate property to your struct (e.g. of type Action) then just invoke this delegate when you need it. Just set this property to the method you want to call when instantiating the struct instances.
Using a delegate and dictionary<string, delegate>
void Main()
{
var reports = new Dictionary<string, Report>
{
{"Daily_Unload", ReportDailyUnLoad}
};
var report = "Daily_Unload";
reports[report]();
}
delegate string Report();
string ReportDailyUnLoad()
{
return "daily unload report";
}

Categories

Resources