C# Passing Function as Argument
Solution 1
Using the Func as mentioned above works but there are also delegates that do the same task and also define intent within the naming:
public delegate double MyFunction(double x);
public double Diff(double x, MyFunction f)
{
double h = 0.0000001;
return (f(x + h) - f(x)) / h;
}
public double MyFunctionMethod(double x)
{
// Can add more complicated logic here
return x + 10;
}
public void Client()
{
double result = Diff(1.234, x => x * 456.1234);
double secondResult = Diff(2.345, MyFunctionMethod);
}
Solution 2
There are a couple generic types in .Net (v2 and later) that make passing functions around as delegates very easy.
For functions with return types, there is Func<> and for functions without return types there is Action<>.
Both Func and Action can be declared to take from 0 to 4 parameters. For example, Func < double, int > takes one double as a parameter and returns an int. Action < double, double, double > takes three doubles as parameters and returns nothing (void).
So you can declare your Diff function to take a Func:
public double Diff(double x, Func<double, double> f) {
double h = 0.0000001;
return (f(x + h) - f(x)) / h;
}
And then you call it as so, simply giving it the name of the function that fits the signature of your Func or Action:
double result = Diff(myValue, Function);
You can even write the function in-line with lambda syntax:
double result = Diff(myValue, d => Math.Sqrt(d * 3.14));
Solution 3
public static T Runner<T>(Func<T> funcToRun)
{
//Do stuff before running function as normal
return funcToRun();
}
Usage:
var ReturnValue = Runner(() => GetUser(99));
Related videos on Youtube
Ash
Updated on March 22, 2022Comments
-
Ash over 2 years
I've written a function in C# that does a numerical differentiation. It looks like this:
public double Diff(double x) { double h = 0.0000001; return (Function(x + h) - Function(x)) / h; }
I would like to be able to pass in any function, as in:
public double Diff(double x, function f) { double h = 0.0000001; return (f(x + h) - f(x)) / h; }
I think this is possible with delegates (maybe?) but I'm not sure how to use them.
-
Davide Cannizzo almost 4 yearsDoes this answer your question? Pass Method as Parameter using C#
-
-
Joel Mueller almost 14 years
-
Ani almost 14 yearsA really cool thing to do would be to return a
Func<double, double>
that is the first-derivative of the input function, numerically calculated of course.return x => (f(x + h) - f(x)) / h;
You could even write an overload that returned then
th derivative of the input function. -
KeithS almost 14 yearsIn 3.5 and later, Func<>s and delegates are interchangeable, and that means that anonymous delegates and lambdas (which are syntactic sugar for anonymous delegates) can also be used. So it doesn't really matter whether you specify the parameter as a Func<double,double> or a delegate that takes a double and returns a double. The only real advantage a named delegate gives you is the ability to add xml-doc comments; descriptive names are just as easy to implement as the parameter name instead of the type.
-
Ian Johnson almost 14 yearsI would argue that the method prototype still makes the code more readable than the Func<x, y> - it is not just the naming that makes code readable and as you say that does not stop you from passing lambdas into the code.
-
quentin-starin almost 14 yearsIf the naming of the delegate type is so important to code clarity, I think in most cases I'd be leaning towards an interface and implementations.
-
Ian Johnson almost 14 years@qstarin it is not just the naming of the delegate but the naming of the arguments that the method must take, especially if they are just native types. You are right, mostly I use interfaces over delegates
-
kdbanman almost 9 yearsI'm curious, why the generic type parameter?
-
DermFrench almost 9 yearsI'm getting this error: The type arguments for method 'Runner<T>(Func<T>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
-
kravits88 almost 9 yearsWhat's your "funcToRun" method signature?
-
Dan Chase almost 5 yearsIf I'm making one of these as a common function that provides common functionality, (with a not-so-common return type) everything works until I try to use it with void. Do I really need to make a duplicate function using Action instead of Func or is there a better way?
-
David Bandel over 3 yearsThis is a pretty abstruse example for someone unfamiliar with delegates. Was the lambda expression really necessary?