Click here to Skip to main content
15,867,594 members
Articles / Programming Languages / C# 5.0
Tip/Trick

Uses of Func in C#

Rate me:
Please Sign up or sign in to vote.
4.60/5 (22 votes)
11 May 2014CPOL2 min read 110.6K   23   14
Uses of Func in C#

What is Func?

Func in short is parameterized delegate. In C#, a delegate instance points towards a method. When a caller invokes the delegate, it calls its target method. This way, the caller is not invoking the target method rather invoking the delegate which can call the target method. We do it because it creates an abstraction on invoking the target method. We of course always can invoke a method directly but decoupling of the client and target method is sometimes a need or gives us more flexibility to make things clean and simple.

We can use Func delegate to represent a method that can be passed as a parameter without explicitly declaring a custom delegate.

Why I said it's a parameterized delegate:

C#
delegate TResult Func <out TResult> ();
delegate TResult Func <in T, out TResult> (T arg);

delegate TResult Func <in T1, in T2, out TResult> (T1 arg1, T2 arg2);

... and so on, up to T16   

The Problem

To understand use of Func, we must understand what problems it can solve. Let's say we have an int array here.

C#
IEnumerable<int> numbers = new[] {3, 4, 7, 1, 8, 10, 21, 5, 9, 11, 14, 19};

It's a simple array. If we want to print the numbers which are greater than 10, we will write a method like below. We will send the array as parameter and will get another array which will contain the numbers that are greater than 10.

C#
public IEnumerable<int> GetGreaterThanTen(IEnumerable<int> numbers)
{
    foreach (int number in numbers)
        if (number > 10)
            yield return number;
} 
…and then if we want to print the numbers which will have result less than 1 after divided by 5, we will write a method:
C#
public IEnumerable<int> GetGreterThanOneAfterDevidedByFive(IEnumerable<int> numbers)
{
    foreach (int number in numbers)
        if ((number/5) > 1)
            yield return number;
}

The Solution

In the above way, we will add more methods as the new conditions come. But there is a better way to face this problem. We can and should use delegate to avoid rewriting a fresh method every time we get by a new rule we want to apply for this array. Use of Func as method parameter we will have the leverage to decouple the caller and the function we want to use. Func will pass the rule to the method body and will apply it.

C#
public IEnumerable<int> GetNumbers(IEnumerable<int> numbers, Func<int, bool> numberResolver)
{
    foreach (int number in numbers)
        if (numberResolver(number))
            yield return number;
}
IEnumerable<int> numbers = new[] {3, 4, 7, 1, 8, 10, 21, 5, 9, 11, 14, 19};

IEnumerable<int> greaterThanTen = GetNumbers(numbers, x=>x>10);
greaterThanTen.ToList().ForEach(Console.WriteLine);

Console.WriteLine("\n");

IEnumerable<int> greaterThanOneAfterDividedByFive = GetNumbers(numbers, n => (n/5) > 1);
greaterThanOneAfterDividedByFive.ToList().ForEach(Console.WriteLine);

The above code is pretty self-explanatory. Func uses Lambda expression which is essentially an anonymous function.

For extensibility standpoint, Func is very effective. While writing various extension methods, you will find it extremely useful.

Getting TResult

The x-factor of Func is probably Func<TResult>. For functional programming, the return type has great use. For example:

C#
Func<int, int> square = num => num*num;
Console.WriteLine(square(3));

…also, we can bring the previous example here see a bit more complex scenario.

C#
IEnumerable<int> numbers = new[] { 3, 4, 7, 1, 8, 10, 21, 5, 9, 11, 14, 19 };
Func<IEnumerable<int>, IEnumerable<int>> getGreaterThanTen = nums => 
{
    var array = new List<int>();
    nums.ToList().ForEach(x =>
    {
        if (x > 10)
            array.Add(x);
    });
    return array;
};

var result = getGreaterThanTen(numbers);

result.ToList().ForEach(Console.WriteLine);

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Bangladesh Bangladesh
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionMy vote of 5!, Simple & Excellent Explanation Pin
VR Karthikeyan3-Jun-16 1:08
professionalVR Karthikeyan3-Jun-16 1:08 
QuestionReally easy to understand! Helpful to me. Thanks Pin
Member 1115961323-Aug-15 3:06
Member 1115961323-Aug-15 3:06 
QuestionVery nice. Easy to understand! Pin
Member 1086450826-Mar-15 4:14
Member 1086450826-Mar-15 4:14 
QuestionMy Vote of 5 Pin
Faisal(mfrony)14-May-14 1:33
Faisal(mfrony)14-May-14 1:33 
GeneralMy vote of 5 Pin
Monjurul Habib14-May-14 1:09
professionalMonjurul Habib14-May-14 1:09 
GeneralRe: My vote of 5 Pin
Md Nazmoon Noor14-May-14 1:24
Md Nazmoon Noor14-May-14 1:24 
QuestionWon't Work Pin
hansonprogrammer12-May-14 17:23
hansonprogrammer12-May-14 17:23 
AnswerRe: Won't Work Pin
Md Nazmoon Noor13-May-14 1:42
Md Nazmoon Noor13-May-14 1:42 
GeneralMy vote of 5 Pin
Humayun Kabir Mamun11-May-14 21:28
Humayun Kabir Mamun11-May-14 21:28 
GeneralRe: My vote of 5 Pin
Md Nazmoon Noor11-May-14 21:35
Md Nazmoon Noor11-May-14 21:35 
GeneralMy vote of 2 Pin
Alexander Sharykin11-May-14 20:12
Alexander Sharykin11-May-14 20:12 
Examples are obsolete since .Net 3.5 when LINQ was released
Does this tip give anything new what can't be found in MSDN?
Func<T,TResult> delegate
QuestionFormat Pin
Nelek11-May-14 6:15
protectorNelek11-May-14 6:15 
AnswerRe: Format Pin
Md Nazmoon Noor11-May-14 7:11
Md Nazmoon Noor11-May-14 7:11 
GeneralRe: Format Pin
Nelek11-May-14 7:42
protectorNelek11-May-14 7:42 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.