Func is generally used for those methods which are going to return a value, or in other words, Func delegate is used for value returning methods. It can also contain parameters of the same type or of different types.
Action is a delegate (pointer) to a method, that takes zero, one or more input parameters, but does not return anything. Func is a delegate (pointer) to a method, that takes zero, one or more input parameters, and returns a value (or reference).
Func is a generic delegate included in the System namespace. It has zero or more input parameters and one out parameter. The last parameter is considered as an out parameter. The Func delegate that takes one input parameter and one out parameter is defined in the System namespace, as shown below: Signature: Func.
The Func accepts a string parameter (the id of the record to fetch) and returns a Task of type RecordType (a generic type parameter). In the following example, Employee will be specified for the generic type. This means when the Func is awaited, it'll return an Employee object.
Think of it as a placeholder. It can be quite useful when you have code that follows a certain pattern but need not be tied to any particular functionality.
For example, consider the Enumerable.Select
extension method.
This method takes a Func<T, TResult>
instead of any concrete function. This allows it to be used in any context where the above pattern applies.
So for example, say I have a List<Person>
and I want just the name of every person in the list. I can do this:
var names = people.Select(p => p.Name);
Or say I want the age of every person:
var ages = people.Select(p => p.Age);
Right away, you can see how I was able to leverage the same code representing a pattern (with Select
) with two different functions (p => p.Name
and p => p.Age
).
The alternative would be to write a different version of Select
every time you wanted to scan a sequence for a different kind of value. So to achieve the same effect as above, I would need:
// Presumably, the code inside these two methods would look almost identical;
// the only difference would be the part that actually selects a value
// based on a Person.
var names = GetPersonNames(people);
var ages = GetPersonAges(people);
With a delegate acting as placeholder, I free myself from having to write out the same pattern over and over in cases like this.
Func<T>
is a predefined delegate type for a method that returns some value of the type T
.
In other words, you can use this type to reference a method that returns some value of T
. E.g.
public static string GetMessage() { return "Hello world"; }
may be referenced like this
Func<string> f = GetMessage;
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With