Click here to Skip to main content
15,896,730 members
Articles / Programming Languages / C# 5.0

Delegates (Delegate, Func, Predicate, Action and Lambda)

Rate me:
Please Sign up or sign in to vote.
4.73/5 (27 votes)
8 Nov 2014CPOL4 min read 47.9K   54   20
A detailed description for Delegate, Func, Predicate, Action and Lambda Expression.

Introduction

In this article I am going to describe some confusing terms including Func, Action, Predicate, lambda expression and delegate and their differences. Although the introduction of generics and lambda expressions added a bit to the complexity of these terms, they are all the same, Delegates.

This helps you to have a better understanding of these terms and could possibly solve complex interactions between objects and collections.

Background

Delegate has existed in the programming world since a long time ago, however throughout the time many forms of delegates have been added to .Net for the purpose of creating more ways to solve problems.

Let's start with a simple definition of delegates. A delegate is a reference to a piece of code that does something!, exactly like a method. It has arguments as input and results as output.

C#
delegate(int x) {

    return x == 0;
}

If we replace the delegate keyword with 

C#
public bool FunctionName

then it would become

C#
public bool FunctionName(int x){
    return x == 0;
}

so basically in one form it could be a function without a name and more technically an anonymous function. A delegate can also have a name like below and it refers to a method with the same signature.

C#
public bool delegate Name(int x);

and then this could be associated with an event so that other objects can subscribe to it and be notified whenever the event is fired (which is out of scope for this article).

Now that we know what a delegate is, let's use it somewhere exciting such as LINQ and collections. Say we have a collection like this:

C#
var collection = new List<int>();
collection.Add(1);
collection.Add(2);
collection.Add(3);

If we want to filter the elements of this collection, we normally write something like:

C#
collection.Where(x => x == 2);

I will get back to lambda expressions and explain them as part of this article.

Delegate

Now what if I want to describe the condition inside parenthesis with a delegate. Remember a delegate is supposed to reference to a piece of code that does something so basically like a method. So why not comparing some elements and filter them for us, like the lambda expression that I talked about. So what if I write something like:

delegate(int item)
{
    if(item == 2)
    {
        return true;
    }
    return false;
}

and subsequently:

collection.Where(delegate(int item)
            {
                if (item == 2)
                {
                    return true;
                }
                return false;
            });

How was that? So simply this was a delegate which was taking an integer as an input and was returning a boolean as output.

Func

Another form of a delegate is Func. Func could have any number and type of input arguments and could return any type of output, exactly like a delegate. The signature is something like:

Func<int, bool> condition = delegate(int item)
{
    if(item == 2)
    {
        return true;
    }
    return false;
};

Because Func could return any type, we need to mention the return type in the signature (in this case the bool, which is literrally the last argument in the generic definition.

Func<int, bool> condition = deleg...

And I can write:

var result = collection.Where(condition);

Predicate

If a Func only returns a bool, that would have another name called a Predicate, just to confuse us a bit more. So a predicate is a delegate that always returns a boolean with any number and type of inputs. Therefore:

Predicate<int> predicate = delegate(int item)
{
    if(item == 2)
    {
        return true;
    }
    return false;
};

However we need to convert this predicate to a Func if we want to use it like before:

Func<int, bool> condition = new Func<int, bool>(predicate);
collection.Where(condition);

But there are situations that we could use a predicate directly:

collection.Find(predicate);

Best Practice: Use Func, Lambda Expressions and Delegates instead of Predicates.

Action

Now what if my Func didn't return any value, what would be that called then? Yes! an Action. So basically an Action is a delegate that does something without any return value. Something like:

Action<int> action = delegate(int item)
{
    item += 2;
}

Can I use this action with the previous example of filtering? Not really, because the argument to the Where method should return a boolean to evaluate whether that item should be included in the result or not, right? So Where can I use an Action?

The answer is whenever I wanted to do an operation without any return value. like:

collection.ForEach(action);

So this will run for every item in the collection and adds 2 to each item. However note that although this action is run for each item in the collection, in this case the change is not applied because we are modifying a collection using a LINQ for each loop which is not allowed. But it was a Reference type, properties of that type could be changed in a for each loop, like the samples below.

Lambda Expression

Now I'd like to define another synonym for a delegate, a Lambda Expression. A lambda expression can be in the form of a Func or an Action, and therefor inherently it's a delegate. 

So the replacement for the Where argument could be:

Predicate<int> condition = (int x) => x == 2;
Func<int, bool> condition = (int x) => x == 2;

and for the ForEach method I can write:

Action<int> action = (int item) => item += 2;

And that's it. We are there, with all the confusion gone. I have written some samples below for each of these terms in a more complicated fashion. Hope it helps.

Samples

public class Customer
{
    public string Name { get; set; }
    public string Telephone { get; set; }
}
var customers = new List<Customers>();

customers.Add(new Customer() {
    Name = "cust A",
    Telephone = "123"
});
​customers.Add(new Customer() {
    Name = "cust B",
    Telephone = "456"
});
​customers.Add(new Customer() {
    Name = "cust C",
    Telephone = "789"
});

1. Delegate 

customers.Where(delegate(Customer cust) {
    return cust.Name == "cust B";
});

2. Func

Func<Customer, bool> filter = delegate(Customer cust){

    return cust.Name == "cust B";
};

customers.Where(filter);

3. Predicate

Predicate<Customer> filter = delegate(Customer cust){

    return cust.Name == "cust B";
};

customers.Find(filter);

4. Lambda

Func<Customer, bool> filter = (Customer cust) => cust.Name == "cust B";

customers.Where(filter);

5. Action

We can't use Actions here because it doesn't return any value let alone bool.

Now lets play with ForEach method, instead of filtering data:

1. Delegate

customers.ForEach(delegate(Customer cust){
    cust.Name = "cust B name Modified !!!";
});

2. Func

We can't use Func here, as Func has to always return something.

3. Predicate

We can't use predicate here as well, as it always has to return boolean.

4. Lambda

customers.ForEach(cust => cust.Name = "cust B Modified !!!");

5. Action

Action<Customer> filter = (Customer cust) => cust.Name = "cust B Modified !!!";

customers.ForEach(filter);

*) Now a key question! why the following code snippet has a compilation error:

C#
var simpleDelegate = delegate(int x) {

    return x == 0;
};

The answer is, because as you saw, there are different structures (predicate, func, delegate) that could be associated to this delegate, and the compiler doesn't know which one to pick J.

License

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


Written By
Technical Lead
Australia Australia
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionLike others have said Pin
leon de boer21-Oct-16 8:20
leon de boer21-Oct-16 8:20 
GeneralMy vote of 5 Pin
Member 292436726-Jun-15 14:33
Member 292436726-Jun-15 14:33 
GeneralWell defined and explained. Pin
Narasimhan Jayachandran31-Dec-14 5:58
Narasimhan Jayachandran31-Dec-14 5:58 
GeneralMy vote of 1 Pin
s2bert1-Dec-14 23:42
s2bert1-Dec-14 23:42 
GeneralRe: My vote of 1 Pin
KarstenK12-Dec-14 4:28
mveKarstenK12-Dec-14 4:28 
GeneralRe: My vote of 1 Pin
s2bert12-Dec-14 13:43
s2bert12-Dec-14 13:43 
GeneralRe: My vote of 1 Pin
Mahdi K.12-Dec-14 13:52
Mahdi K.12-Dec-14 13:52 
QuestionDocs are boring Pin
Thornik11-Nov-14 7:43
Thornik11-Nov-14 7:43 
AnswerRe: Docs are boring Pin
Mahdi K.11-Nov-14 9:35
Mahdi K.11-Nov-14 9:35 
GeneralRe: Docs are boring Pin
Thornik12-Nov-14 3:43
Thornik12-Nov-14 3:43 
GeneralMy vote of 2 Pin
s2bert11-Nov-14 4:06
s2bert11-Nov-14 4:06 
GeneralRe: My vote of 2 Pin
Mahdi K.1-Dec-14 18:12
Mahdi K.1-Dec-14 18:12 
GeneralSuper Pin
Valentino_Lokesh10-Nov-14 7:22
Valentino_Lokesh10-Nov-14 7:22 
GeneralMy vote of 5 Pin
Humayun Kabir Mamun9-Nov-14 21:40
Humayun Kabir Mamun9-Nov-14 21:40 
QuestionIs it true that a lambda expression is inherently a delegate? Pin
George Swan9-Nov-14 21:14
mveGeorge Swan9-Nov-14 21:14 
AnswerRe: Is it true that a lambda expression is inherently a delegate? Pin
s2bert10-Nov-14 6:02
s2bert10-Nov-14 6:02 
GeneralRe: Is it true that a lambda expression is inherently a delegate? Pin
Mahdi K.10-Nov-14 16:38
Mahdi K.10-Nov-14 16:38 
GeneralRe: Is it true that a lambda expression is inherently a delegate? Pin
s2bert10-Nov-14 23:04
s2bert10-Nov-14 23:04 
GeneralRe: Is it true that a lambda expression is inherently a delegate? Pin
Mahdi K.10-Nov-14 23:19
Mahdi K.10-Nov-14 23:19 
GeneralRe: Is it true that a lambda expression is inherently a delegate? Pin
s2bert11-Nov-14 3:19
s2bert11-Nov-14 3:19 
Sorry, but that's simply not true though I agree we're not talking about philosophy with different interpretations. There's no philosophy to it at all, just language features versus framework features.

The clue is in the name. In C# it's a means to express either an anonymous / inline function that can be bound to a delegate (which you can also do in another way) OR to express and hence initialise an expression tree (which you can also do in another way). If this doesn't make it clear that it's a language feature, I'm not sure what does. A delegate is a .Net framework feature. So your first clue is there. They're not the same thing.

You can read about it here:

http://msdn.microsoft.com/en-us/library/bb397951.aspx
http://msdn.microsoft.com/en-gb/library/bb882516.aspx

You can see more clearly that lambda expressions are a feature of the language if you contrast the C# lambda syntax with the VB lambda syntax, which is far more clear in terms of defining anonymous functions:

http://msdn.microsoft.com/en-us/library/bb531253.aspx

As you can see in the above article, it refers to lambda expressions as "functions or subroutines without a name" that can be used wherever a delegate is valid. In the same way that I can express a value for a double, using a literal: "double a = 1.0" I can express a value for a delegate using a lambda expression. There's no philosophy, the delegate exists in the output, whereas the literal and the lambda expression are consumed by the compiler in order to output the delegate implementation. You may say this is only a philosophical difference, but it's really not, it's the same "philosophical difference" between C#, VB and the .Net framework, these all deal with related concepts, but they are not the same thing.

A delegate defines a function or subroutine, a variable of a given delegate type can be assigned its value from any suitable function or subroutine, whether defined inline or referenced by name within the appropriate scope. In no way is the delegate the function. And in no way is the delegate the lambda expression. The lambda expression is closer to being a function than it is a delegate. Nobody would argue that delegate IS a function. Any more than a pointer to a function is a function.

So to wrap up, a lambda CAN BE USED to define an inline function. In C# it has at least one other use, to define expressions for expression trees. This is why they gave it a name. It's an expression - a lambda expression. It has syntax. It's not a delegate and there's no philosophy to it, just a syntax, which makes it a language feature (you can see this in the vast difference between the VB and C# versions) hence why as I said it's the C# compiler that ultimately decides what to do with your expression, either compile it to something that can be bound to an expression tree or to a delegate. There's no philosophy there, just a plain and simple feature of the C# langue distinct from delegates which are a feature of the .Net framework.

As you'll find if you try it out, an expression tree is in no way a delegate, and yet a lambda can be used to express one.

So is a lambda expression a delegate? Philosophically or otherwise?

Of course not.

You even said it yourself in your article:

"A delegate is a reference to a piece of code that does something!, exactly like a method."

Lets try swapping "lambda expression" for delegate there...

"A lambda expression is a reference to a piece of code that does something!, exactly like a method."

Not quite right is it?

A lambda expression is a delegate no more than a literal is a variable.

modified 11-Nov-14 10:04am.

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.