How to create a fully parameterized method delegate in C#? - c#

In c# we can create delegates via a variety of means (e.g. Action<>, Func<>, delegate, lambdas, etc). But when you invoke those methods, you have to provide the parameter values for the delegate you are invoking:
delegate int del(int i);
del myDelegate = x => x * x;
int j = myDelegate(5);
Is there a way in c# to encapsulate a method delegate WITH parameter values? Essentially delay invocation of a fully parametrized method? So you don't have to supply parameter values at invocation time?
For example something like this invalid code:
delegate int del(int i);
del myDelegate(5) = x => x * x;
int j = myDelegate;
I'm aware the use case isn't immediately obvious. In the case I'm currently looking at, I have a non-deterministic method that I would like the caller to be able to invoke without having to contain or be aware of the parameters the method needs. One way to achieve this would be via creating a class that encapsulates both the parameter values and the method delegate and have that referenced and invoked by the caller. But I'm just curious if there is an alternate, more succinct way.

This is called currying.
For example:
Action curried = () => myFunc(5);
Or,
Func<int, int, int> multiplier = (x, y) => x * y;
Func<int, int> doubler = x => multiplier(x, 2);
int eight = doubler(4);

Func<int, int> myDelegate = x => x * x;
Func<int> myDelegate5 = () => myDelegate(5);
int j = myDelegate5();

You could always wrap one delegate in another. As SLaks mentioned, this is called currying:
Func<int, int> square = i => i * i;
Func<int> squareFive = () => square(5);
int j = squareFive();

This can be done reasonably nicely without lambdas, with the aid of some generic classes and helper functions. I used such an approach in some vb.net/vs2005 code. If the goal is to yield a MethodInvoker which calls a function with three arguments of types T, U, and V, then create a class ParamInvoker<T,U,V> which holds fields param1, param2, and param3 (as types T, U, and V), and Action (of type Action<T,U,V>) and has a method DoIt(void) which calls Action(param1, param2, param3). The generic classes and helper functions get repetitive, but the syntax is pretty nice. For example (vb syntax, from memory, and C# syntax, guessing):
TheMethodInvoker = MakeParamInvoker(AddressOf MyFunction, 5, "Hello")
or
TheMethodInvoker = MakeParamInvoker(MyFunction, 5, "Hello")
assuming MyFunction takes an Integer and a String.

Related

Why can't you invoke the fuction directly with the parameters with Func?

I just have a question about the Func and Action delegate.
I just wonder why you can't do this directly:
public static int addTowNumber(int a, int b)
{
return a + b;
}
Func<int, int, int> add = addTowNumber(1,2);
But you have to do this:
Func<int, int, int> add = addTowNumber;
var addNumber = add(1, 2);
Console.WriteLine(addNumber);
By passing the arguments you are actually invoking the method, and returning an int.
To store a reference to a function, to be invoked later, you don't pass the arguments, which is why this is correct:
Func<int, int, int> add = addTowNumber;
You can then provide any arguments you like when invoking:
int result1 = add(1, 2);
int result2 = add(3, 4);
If you want to defer execution of a method with predefined arguments, which is what it appears you are trying to do, you need to create a closure like this:
Func<int> add = () => addTowNumber(1, 2);
int result = add();

What is the different in the lambda expression from group1 and group2?

What is the difference between Group1 and Group2 in the following syntax. I have just started using these types of expressions and I see one that has a delegate and looks like a function (for the most part) and then I see Group1 (=>) with this syntax and I'm not certain which is different or which is better.
It also says that Func<> should only take two arguments but in Group1 example it takes three variables. Why is that?
http://msdn.microsoft.com/en-us/library/bb549151(v=vs.110).aspx
Group1
Action<bool> print1 = q => Console.WriteLine(q);
Action<int> printInt = q => Console.WriteLine(q);
Func<double, double> square1 = c => c * c;
Func<double, double, double> add1 = (x, y) => x + y;
Predicate<double> isLessThanTen1 = f => f < 10;
Group2
Func<string, string> convert = delegate(string s)
{
return s.ToUpper();
};
Group 1 is a shorthand way of creating a delegate, without the need for delegate(). It's "preferred" because it's shorter and easier to read.
Action<> is a delegate that takes an argument (or multiple) and returns void
Func<> is a delegate that takes an argument (or multiple) and returns something
Predicate<> is a delegate that takes an argument (or multiple) and returns bool
In other words
Func<int, void> == Action<int>
and
Func<int, bool> == Predicate<int>
In the MSDN page you linked to, there's other overloads of Func<> that take a varying amount of parameters. For example, here's a version that accepts 4 parameters.
One of the best resources on the topic is C# in Depth by Jon Skeet. It gives a nice history of delegates and the syntax changes in each version of C#.

How to make an anonymous method accept variable number of arguments?

I'd like to be able to make inline calls to anonymous methods with variable number of arguments (sometimes with no arguments, sometimes with 11).
Dictionary<string, Action> ActionDic = new Dictionary<string, Action>();
int i = 0;
ActionDic["something"] = () => { i += 1; }; // this line is ok
ActionDic["somethingArgs"] = (int n) => { n += 1; }; // but this is not
// Delegate 'System.Action' does not take 1 arguments
So I can't make a delegate accept arguments like that. Is my syntax wrong, or is it just not possible? Or do I have to change the type of anonymous method I should use for my dictionary?
You could use Action<int> if you want to define a delegate with 1 integer argument. For example:
Action<int> somethingArgs = (int n) => { n += 1; };
You haven't shown what the ActionDic variable is but if it is an IDictionary<string, Action> you cannot make this work because Action do not accept an argument.
What you could do on the other hand is to use a dictionary of delegates:
IDictionary<string, Delegate> ActionDic = ...
ActionDic["something"] = (Action)(() => { i += 1; });
ActionDic["somethingArgs"] = (Action<int>)((int n) => { n += 1; });
You can't. Action and Action<T> are different, incompatible delegate types.
There are several ways to compensate for this.
One would be to make ActionDic a Dictionary<string, Action<int>> but that may not satisfy all possible delegates you would want to use.
Another would be to make ActionDic something like a Dictionary<string, Delegate> but this would cumbersome to use because you need to know exactly how many many parameters (and their types) to pass each function. This information would need to be stored in another data structure somewhere.
Still a third way would be to make ActionDic a Dictionary<string, Action<object[]>> and require the delegate to unpack whatever arguments it needs from the input. The caller would be responsible for knowing exactly what arguments to use. This would allow somewhat less awkward syntax of the second option, but require more code in each delegate.
You are talking about two different delegates, i.e. Action and Action<T>. You cannot assign Action<T> to Action:
Action a1 = () => { i += 1; };
Action<int> a2 = (n) => { n += 1; };
I suppose you're having Dictionary<string,Action>, so this dictionary cannot accept a value of Action<T>.
As a side note, I'd say that the second delegate is absolutely useless, as it increments an int argument, passed by value, that is in fact doing nothing.
Also consider reading How To pass Optional Arguments. Though it has nothing to do with anonymous methods, but it may give you some clue on how to pass variable number of arguments
Action is a short way to create a delegate that returns void and take no argument.
If you want actions with argument, you need to use generic form :
Action<int> is a delegate that takes one int parameter
Action<string, double> takes 2 parameters : first is string second is double.

Is there a way to cast a function

I think it would greatly simplify function overloading if I could just write the case that takes the most parameters and then simply stuff each case having less parameters with dummy params. For example..
// Add two integers
Func<int, int, int> addInts = (x, y) => { return x + y; };
// Add one to an integer
Func<int, int> addOne = (x) => { return x++; };
// In this case Func takes 2 args and has 1 return
public int IntCalc(Func<int,int,int> operation, int param1, int param2)
{
return operation(param1, param2);
}
// In this case Func takes 1 arg and has 1 return
public int IntCalc(Func<int, int> operation, int param1, int param2)
{
// This cast would allow me to do the overload
Func<int, int, int> castedOperation = (Func<int, int, int>)addOne;
return IntCalc(castedOperation, param1, 0);
}
So is there a way to do this? Is this a horrible practice?
You can only cast if the parameter signatures are compatible. In your case you'd need to define a lamda since converting a function with one parameter to a function with two parameters makes no sense in general.
Func<int, int, int> castedOperation = (i1,i2)=>addOne(i1);
If it's good practice depends on the contract of how the delegate will be used. If your functions with less parameters can fulfill that contract then this lamda based conversion is perfectly fine.
As a sidenode your addOne function is really ugly. While the increment of x has no effect because the parameter gets copied and thus only the copy is incremented and discared, implementing it as return x+1; would be much nicer than return x++; since you don't actually want to modify x.
Apart from the accepted answer you should also change the addOne to operation. So complete function would be
// In this case Func takes 1 arg and has 1 return
public int IntCalc(Func<int, int> operation, int param1, int param2)
{
// This cast would allow me to do the overload
Func<int, int, int> castedOperation = (i1,i2)=>operation(i1);
return IntCalc(castedOperation, param1, 0);
}
If your all parameters are the same type you can use params
adder(bool sample, params int[] a)
{
....
}
adder(2,3,4);
also you can use Named Parameter in C# 4.0.
Your approach is useful in constructors (you can do this with them).

Why I cannot use the anonymous method like that?

Why can't I have this? I mean it would spare a delegate declaration:
int X=delegate int(){...};
I know it can be done this way:
delegate int IntDelegate();
...
IntDelegate del=delegate(){return 25;};
int X=del();
A delegate is not an int.
If you use .Net 3.5 or newer you can use the built in Func instead of using a custom (Func also have generic types if you need arguments like Func which tages a string and return an int):
Func<int> X = delegate() { return 255; };
or with lambda expressions:
Func<int> X = () => 255;
Unfortunately, you can't say:
var X2 = () => 255;
in C# but you can do something similar in functional languages ex F#. Instead you would say the following in C#:
var X2 = new Func<int>(() => 255);
Tomas,
would this work for you:
delegate int IntDelegate();
// other stuff...
IntDelegate _del = () => 25;
jim
[edit] - oops, just realised, the question was re making it a one liner!! - i'll have a think
Because in the first example, you're trying to assign a delegate type into an int, rather than the output of a delegate into an int. A delegate is a type that stores a function, which just so happens to return a value that you're interested in.
Is there really a need for creating a delegate, executing it, and returning the value?
Why not just execute the code directly?
int x = new Func<int,int>(num => num*num) (3);
would return 9, but so would:
int x = 3*3;

Categories

Resources