863

With real examples and their use, can someone please help me understand:

  1. When do we need a Func<T, ..> delegate?
  2. When do we need an Action<T> delegate?
  3. When do we need a Predicate<T> delegate?
Neuron
  • 5,141
  • 5
  • 38
  • 59
InfoLearner
  • 14,952
  • 20
  • 76
  • 124

3 Answers3

1065

The difference between Func and Action is simply whether you want the delegate to return a value (use Func) or not (use Action).

Func is probably most commonly used in LINQ - for example in projections:

 list.Select(x => x.SomeProperty)

or filtering:

 list.Where(x => x.SomeValue == someOtherValue)

or key selection:

 list.Join(otherList, x => x.FirstKey, y => y.SecondKey, ...)

Action is more commonly used for things like List<T>.ForEach: execute the given action for each item in the list. I use this less often than Func, although I do sometimes use the parameterless version for things like Control.BeginInvoke and Dispatcher.BeginInvoke.

Predicate is just a special cased Func<T, bool> really, introduced before all of the Func and most of the Action delegates came along. I suspect that if we'd already had Func and Action in their various guises, Predicate wouldn't have been introduced... although it does impart a certain meaning to the use of the delegate, whereas Func and Action are used for widely disparate purposes.

Predicate is mostly used in List<T> for methods like FindAll and RemoveAll.

Noctis
  • 11,507
  • 3
  • 43
  • 82
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 90
    I rather like seeing `Predicate` in a function signature. It illustrates that the passed method makes a decision rather than just returns a success code or a different sort of `bool`. – Ron Warholic Nov 30 '10 at 19:15
  • 8
    Is there any design guideline on whether to prefer `Predicate` or `Func`? I like the expressiveness of `Predicate`, but I've seen recommendations for `Func` too. – CodesInChaos Nov 30 '10 at 19:16
  • 6
    @Ron: Yes, that's pretty much what my penultimate paragraph was about. – Jon Skeet Nov 30 '10 at 19:16
  • 7
    @CodeInChaos: Not that I've seen. LINQ uses `Func` throughout, but that's probably for consistency given that many method accepting a `Func` as a predicate also have an overload taking a `Func` for an indexed predicate. – Jon Skeet Nov 30 '10 at 19:17
  • 6
    i kind'a like how simple you have explained it. func - returns action - performs (method) – Juvil Jan 10 '13 at 05:09
  • 1
    Who tought it would be useful to have 3 different name for the same thing? It's just a **function pointer**! – gimbar Dec 03 '13 at 13:54
  • 2
    @JonSkeet, Yes, but your second-to-last paragraph reads like a history of how things went down, hiding that intent in the middle of it and making it look like an off-comment. @Ron's comment is clear in that it's a desirable effect (not just a byproduct of software evolution), and makes the point that an intentional choice may be made to use `Predicate`s in some use-cases and `Func<…,bool>`s in others to convey meaning. _Coincidentally, one could say that the difference between your penultimate paragraph and @Ron's comment is like the difference between using `Func` and `Predicate`._ – Slipp D. Thompson Jan 28 '15 at 06:19
  • For what it's worth, in C++ the notion of predicate also means that the function is assumed to be a "pure function", i.e. it should always produce the same result if given the same input, while simple functions-producing-bools do not give such a guarantee. Of course, this is not enforced by the compiler or anything, but explicitly stating that a function parameter is a "predicate" helps documenting this sort of assumption (which can be rather important in some contexts, e.g. for multithreading). – ZeRemz Apr 21 '15 at 08:21
  • Note that Linq (or really overload resolution of both C# and VB) will allow a `Func` where it needs a `Predicate` **but not vice versa:** "cannot convert from 'System.Predicate' to 'System.Func'". – Mark Hurd Jul 26 '15 at 05:56
  • This means that if you create a `Where(this s, Predicate p)` extension method for the handful of cases where you already have a `Predicate` to use in a `Where` clause, suddenly all your `Where` clauses match this new extension method (including the one now recursively used internally expecting it to continue to refer to the existing `Where` extension method :-( ). – Mark Hurd Jul 26 '15 at 06:03
  • 1
    @MarkHurd: I'd have to see the exact situation to understand why overload resolution is behaving in that way. Note that there's a big difference between a lambda expression which can be converted to either a `Func` or a `Predicate`, and a reference to an existing `Predicate`. To call the original extension method, just call it as a static method: `Enumerable.Where(...)` – Jon Skeet Jul 26 '15 at 06:35
  • Part of what I noticed is specific to VB.NET: as far as I can tell there's no equivalent in C# for `Dim IsEven = Function(x As Integer) ((x And 1) = 0)`. The equivalent `var IsEven = (int x) => ((x & 1) == 0);` complains: "Cannot assign lambda expression to an implicitly-typed local variable". – Mark Hurd Jul 26 '15 at 13:22
  • 1
    @MarkHurd: It looks like VB creates a new delegate type for situations like that. – Jon Skeet Jul 26 '15 at 13:39
  • And it means `queryable.Where(IsEven)` is only `IEnumerable` using the Linq-provided `.Where` extensions, but when I provide my own `Predicate` based ones (one for `IEnumerable` and one for `IQueryable`) it is `IQueryable`. – Mark Hurd Jul 26 '15 at 14:11
467

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).

Predicate is a special kind of Func often used for comparisons (takes a generic parameter and returns bool).

Though widely used with Linq, Action and Func are concepts logically independent of Linq. C++ already contained the basic concept in form of typed function pointers.

Here is a small example for Action and Func without using Linq:

class Program
{
    static void Main(string[] args)
    {
        Action<int> myAction = new Action<int>(DoSomething);
        myAction(123);           // Prints out "123"
                                 // can be also called as myAction.Invoke(123);

        Func<int, double> myFunc = new Func<int, double>(CalculateSomething);
        Console.WriteLine(myFunc(5));   // Prints out "2.5"
    }

    static void DoSomething(int i)
    {
        Console.WriteLine(i);
    }

    static double CalculateSomething(int i)
    {
        return (double)i/2;
    }
}
Mahmoud Farahat
  • 5,364
  • 4
  • 43
  • 59
Knasterbax
  • 7,895
  • 1
  • 29
  • 23
  • 40
    Predicate is a delegate that takes generic parameters and returns bool – Martin Nov 08 '13 at 06:04
  • 31
    Nice example! Note that you can also invoke myAction by simply calling it: `myAction(123);`. You don't need to use `.Invoke()` – romar Dec 22 '13 at 07:59
  • and just for completeness if you want to use Func which takes no parameters but returns value (or reference) you should write something like this *Func myFoo = new Func(foo);* and foo definition could be **static double foo(){return 1.0;}** – A.B. Apr 07 '18 at 09:51
  • 3
    @Martin Predicate only takes one parameter. – MarredCheese Mar 19 '19 at 17:01
68

Func - When you want a delegate for a function that may or may not take parameters and returns a value. The most common example would be Select from LINQ:

var result = someCollection.Select( x => new { x.Name, x.Address });

Action - When you want a delegate for a function that may or may not take parameters and does not return a value. I use these often for anonymous event handlers:

button1.Click += (sender, e) => { /* Do Some Work */ }

Predicate - When you want a specialized version of a Func that evaluates a value against a set of criteria and returns a boolean result (true for a match, false otherwise). Again, these are used in LINQ quite frequently for things like Where:

var filteredResults = 
    someCollection.Where(x => x.someCriteriaHolder == someCriteria);

I just double checked and it turns out that LINQ doesn't use Predicates. Not sure why they made that decision...but theoretically it is still a situation where a Predicate would fit.

ViRuSTriNiTy
  • 5,017
  • 2
  • 32
  • 58
Justin Niessner
  • 242,243
  • 40
  • 408
  • 536
  • 3
    I know this is old, but Predicate was not used by LINQ because it predates the Func and Action that we know today, and the latter two can be used to achieve the exact same result in a much better way. – gparent Jan 06 '12 at 22:27
  • 1
    @gparent, why is it better? I think the readability is better when meaningfully-named delegates are used instead of `Func` or `Action`. – Sam Jun 14 '13 at 11:37
  • 3
    It depends how you use delegates, but sometimes the name isn't so important and having to create functions and variables just for one use to me decreases readability. – gparent Jun 14 '13 at 14:15