What is Func<>
and what is it used for?
Func<T1,R>
and the other predefined generic Func
delegates (Func<T1,T2,R>
, Func<T1,T2,T3,R>
and others) are generic delegates that return the type of the last generic parameter.
If you have a function that needs to return different types, depending on the parameters, you can use a Func
delegate, specifying the return type.
Both C# and Java don't have plain functions only member functions (aka methods). And the methods are not first-class citizens. First-class functions allow us to create beautiful and powerful code, as seen in F# or Clojure languages. (For instance, first-class functions can be passed as parameters and can return functions.) Java and C# ameliorate this somewhat with interfaces/delegates.
Func<int, int, int> randInt = (n1, n2) => new Random().Next(n1, n2);
So, Func
is a built-in delegate which brings some functional programming features and helps reduce code verbosity.
It is just a predefined generic delegate. Using it you don't need to declare every delegate. There is another predefined delegate, Action<T, T2...>
, which is the same but returns void.
I find Func<T>
very useful when I create a component that needs to be personalized "on the fly".
Take this very simple example: a PrintListToConsole<T>
component.
A very simple object that prints this list of objects to the console. You want to let the developer that uses it personalize the output.
For example, you want to let him define a particular type of number format and so on.
Without Func
First, you have to create an interface for a class that takes the input and produces the string to print to the console.
interface PrintListConsoleRender<T> {
String Render(T input);
}
Then you have to create the class PrintListToConsole<T>
that takes the previously created interface and uses it over each element of the list.
class PrintListToConsole<T> {
private PrintListConsoleRender<T> _renderer;
public void SetRenderer(PrintListConsoleRender<T> r) {
// this is the point where I can personalize the render mechanism
_renderer = r;
}
public void PrintToConsole(List<T> list) {
foreach (var item in list) {
Console.Write(_renderer.Render(item));
}
}
}
The developer that needs to use your component has to:
implement the interface
pass the real class to the PrintListToConsole
class MyRenderer : PrintListConsoleRender<int> {
public String Render(int input) {
return "Number: " + input;
}
}
class Program {
static void Main(string[] args) {
var list = new List<int> { 1, 2, 3 };
var printer = new PrintListToConsole<int>();
printer.SetRenderer(new MyRenderer());
printer.PrintToConsole(list);
string result = Console.ReadLine();
}
}
Using Func it's much simpler
Inside the component you define a parameter of type Func<T,String>
that represents an interface of a function that takes an input parameter of type T and returns a string (the output for the console)
class PrintListToConsole<T> {
private Func<T, String> _renderFunc;
public void SetRenderFunc(Func<T, String> r) {
// this is the point where I can set the render mechanism
_renderFunc = r;
}
public void Print(List<T> list) {
foreach (var item in list) {
Console.Write(_renderFunc(item));
}
}
}
When the developer uses your component he simply passes to the component the implementation of the Func<T, String>
type, that is a function that creates the output for the console.
class Program {
static void Main(string[] args) {
var list = new List<int> { 1, 2, 3 }; // should be a list as the method signature expects
var printer = new PrintListToConsole<int>();
printer.SetRenderFunc((o) => "Number:" + o);
printer.Print(list);
string result = Console.ReadLine();
}
}
Func<T>
lets you define a generic method interface on the fly.
You define what type the input is and what type the output is.
Simple and concise.
Maybe it is not too late to add some info.
Sum:
The Func is a custom delegate defined in System namespace that allows you to point to a method with the same signature (as delegates do), using 0 to 16 input parameters and that must return something.
Nomenclature & how2use:
Func<input_1, input_2, ..., input1_6, output> funcDelegate = someMethod;
Definition:
public delegate TResult Func<in T, out TResult>(T arg);
Where it is used:
It is used in lambda expressions and anonymous methods.
Func<T1, T2, ..., Tn, Tr>
represents a function, that takes (T1, T2, ..., Tn) arguments and returns Tr.
For example, if you have a function:
double sqr(double x) { return x * x; }
You could save it as some kind of a function-variable:
Func<double, double> f1 = sqr;
Func<double, double> f2 = x => x * x;
And then use exactly as you would use sqr:
f1(2);
Console.WriteLine(f2(f1(4)));
etc.
Remember though, that it's a delegate, for more advanced info refer to documentation.