DEV Community

loading...

Can you pass local functions to a method? If so, what type is a function?

baenencalin profile image Calin Baenen ・1 min read

I know you can make local functions in C#, but can you pass them into a function, e.g. either:

MyClass.MyMethod(int f(int x) {return x*2;});
Enter fullscreen mode Exit fullscreen mode

or

int f(int x) {
    return x*2;
}
MyClass.MyMethod(f);
Enter fullscreen mode Exit fullscreen mode

(if only one can be done, it would be helpful to know which one is wrong)?

And if you can, what is the type of functions? System.Function, or something?

Thanks!
Cheers!

Discussion (3)

pic
Editor guide
Collapse
kspeakman profile image
Kasey Speakman • Edited

Yes you can.

The type for a function that returns void is Action<T> or with multiple parameters, Action<T1, T2, ...>.

The type for a function that returns a value is Func<T, TReturn> or with multiple parameters Func<T1, T2, ..., TReturn>.

So if you want to define a method that takes in a function and an int, it could look like this.

public int PlusOne(Func<int, int> f, int x)
{
    // f is used like a normal function
    var x2 = f(x);
    return x2 + 1;
}

var result = PlusOne(x => x * 2, 1024);
Enter fullscreen mode Exit fullscreen mode

PlusOne could easily be a one-liner, but made it multiple lines for demonstration purposes.

Collapse
baenencalin profile image
Calin Baenen Author

But what if I want to accept ANY kind of function? With a custom amount of args, and a custom return value?

Collapse
kspeakman profile image
Kasey Speakman • Edited

Custom return value is easy. You just have to add a generic parameter(s) to the function.

public U Transform<T, U>(Func<T, U> transformFn, T value)
{
    return transformFn(value);
}
Enter fullscreen mode Exit fullscreen mode

To accept a varied amount of arguments, you will have to add method overloads with different numbers of generic type parameters. Only signatures are shown below.

V Transform<T, U, V>(Func<T, U, V> transformFn, T t, U u);
W Transform<T, U, V, W>(Func<T, U, V, W> transformFn, T t, U u, V v);
X Transform<T, U, V, W, X>(Func<T, U, V, W, X> transformFn, T t, U u, V v, W w);
// etc.
Enter fullscreen mode Exit fullscreen mode

Note that some of the types T, U, V, etc could actually be the same type. Different letters are used in case they are different.

The above code does not make sense to use in practice, but it demonstrates the concept.