Pass any function regardless of its parameters - c#

Assuming that I have the following three methods
void Execute(<What to put here?> method)
{
method();
}
void Function1(string a) { ... }
void Function2(int a) { ... }
how can I pass the functions Function1 and Function2 with designated parameters to the Execute method?
e.g. like this
Execute(Function1("Foo"));
but above example is calling the function, I want it to be called only in the Execute method.
I hope it got clear, if it doesn't, I am looking for a way just like this:
void Execute(Action method)
{
method();
}
void Function3() { ... }
which can then be called like this:
Execute(Function3);
so that Function3 is called in the Execute method, not when invoking the Execute method.
I want to be able to do the same thing, but pass specific parameters to the Function3 method that should be used when it is invoked.

Simply make a lambda out of it:
Execute(() => Function1("Foo"));

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.

C# can implement without class declare as Java

Java can implement interface OnCustomEventListener such as:
classA.setCustomEventListener(new OnCustomEventListener(){
public void onEvent(){
//do whatever you want to do when the event is performed.
}
Does C# can do the same?
No, C# has no direct equivalent to that code, howeever the typical way you would pass some "action" or "callback" to a method would be using a delegate, or the shorter-formed Lambda expression.
classA.SetCustomEventListener( () => {
//do whatever you want to do when the event is performed.
});
The code for that method would look like
public void SetCustomEventListener (Action action)
{
action(); // execute the Lambda passed in
}
Ref:
Action delegate

Delegates with methods that have different number of parameters

I've run into a problem. I have something like that:
public class ListSorter : MonoBehaviour
{
public delegate void MyDelegate();
public static MyDelegate myDelegate;
void Start ()
{
ListSorter.myDelegate += A(5);// <-- here I know i cant do it
ListSorter.myDelegate += B;
myDelegate(); //<-- how to call 2 different function with one delegate?
}
public void A(int iVar)
{
print(iVar);
}
public void B()
{
///...
}
}
So as you see, I already know where and how many of parameters I want to have. The question is how to call those function A and B while function A has a parameter and B doesn't have one?
Wrap the function call in an anonymous delegate that matches the target type (no parameters, no return value):
ListSorter.myDelegate += (() => A(5));
ListSorter.myDelegate += B;
To call A with a fixed parameter you need to create a new method that matches the delegate's signature, namely having no parameters and no return value, who's body calls A, passing 5. You could do this with a new named method, or you could use an anonymous method; both would work fine:
ListSorter.myDelegate += () => A(5);
Other than that, you're properly creating a delegate that calls two methods, so invoking it will invoke both of the method's you've added to it.

how to use Asynchronous delegates on a void return method

i want to make a method async
public static void PrepareData<T>()
{
// prepare data ....
}
i was trying to do the following
Func method = PrepareData<T>;
method.invoke
...
but it complain Func must specify something e,g Func
so my question is, how to make a void return method asyn??
Thanks.
You should use Action instead of Func. The Action family is for functions with a void return type, Func is for those that actually return something.
You have to use the Action<T> instead

c# passing method as the argument in a method

I have a recuring method which shows up many times in my code its basically checking to make sure that the connection to the odbc is ok and then connects but each time this method is called it calls another method and each instance of the main method this one is different, as each method is about 8 lines of code having it 8 times in the code isnt ideal.
so basically i would like to have just one method which i can call passing the name of the new method as an arguement.
so basically like:
private void doSomething(methodToBeCalled)
{
if(somthingistrue)
{
methodToBeCalled(someArgument)
}
}
is this possible?
thanks in advance
As already said, you can use delegates for this:
// as in the original post:
private void doSomething(Action methodToBeCalled)
{
if (somethingIsTrue)
{
methodToBeCalled();
}
}
For methods without any arguments, this method is called e.g. as follows:
private void someMethod()
{
// ...
}
doSomething(someMethod);
If you want to call a method with arguments, you can wrap a lambda function around it:
private void someMethodWithArgument(int arg)
{
// ...
}
doSomething( () => someMethodWithArgument(42) );
Of course, if your methods to be called always take the same kind of argument, you can declare your doSomething method so that it accepts an Action<T> / Action<T,T> / etc. argument instead. If you want the called methods to return a value, use a delegate from the Func<T> family instead.
You can use delegates, this is much like a pointer to a function, you can pass a delegate to the method, which will invoke it with the parameter.
public delegate void Del(string message);
// Create a method for a delegate.
public static void DelegateMethod(string message)
{
System.Console.WriteLine(message);
}
// Instantiate the delegate.
Del handler = DelegateMethod;
// Call the delegate.
handler("Hello World");
In your case
private void doSomething(Del methodToBeCalled)
{
if(somthingistrue)
{
methodToBeCalled(someArgument)
}
}
is this possible?
Delegates
use Delegates as your method argument and you can point the delegate to whichever method you want, providing you stick to your delegate signature.
You could also use reflection. Which one is better to use (reflection vs. delegates) depends on the rest of your code. If you're always calling methods that take the same parameters, then a delegate is probably most appropriate. If you need to call methods that take different parameters, then you probably have to use reflection. Looking at your question, it kind of looks like your methods take no parameters, so I'd use delegates as mentioned before.

Categories

Resources