Func vs. Action vs. Predicate

395,304

Solution 1

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.

Solution 2

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;
    }
}

Solution 3

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.

Share:
395,304
InfoLearner
Author by

InfoLearner

Updated on July 08, 2022

Comments

  • InfoLearner
    InfoLearner almost 2 years

    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?
  • Tim_K
    Tim_K over 13 years
    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.
  • CodesInChaos
    CodesInChaos over 13 years
    Is there any design guideline on whether to prefer Predicate<T> or Func<T,bool>? I like the expressiveness of Predicate, but I've seen recommendations for Func too.
  • Jon Skeet
    Jon Skeet over 13 years
    @Ron: Yes, that's pretty much what my penultimate paragraph was about.
  • Jon Skeet
    Jon Skeet over 13 years
    @CodeInChaos: Not that I've seen. LINQ uses Func throughout, but that's probably for consistency given that many method accepting a Func<T,bool> as a predicate also have an overload taking a Func<T,int,bool> for an indexed predicate.
  • Federico Motta
    Federico Motta over 12 years
    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.
  • Juvil
    Juvil over 11 years
    i kind'a like how simple you have explained it. func - returns action - performs (method)
  • Sam
    Sam almost 11 years
    @gparent, why is it better? I think the readability is better when meaningfully-named delegates are used instead of Func or Action.
  • Federico Motta
    Federico Motta almost 11 years
    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.
  • Martin
    Martin over 10 years
    Predicate is a delegate that takes generic parameters and returns bool
  • gimbar
    gimbar over 10 years
    Who tought it would be useful to have 3 different name for the same thing? It's just a function pointer!
  • romar
    romar over 10 years
    Nice example! Note that you can also invoke myAction by simply calling it: myAction(123);. You don't need to use .Invoke()
  • Slipp D. Thompson
    Slipp D. Thompson over 9 years
    @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 Predicates 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<T,bool> and Predicate<T>.
  • ZeRemz
    ZeRemz about 9 years
    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).
  • Mark Hurd
    Mark Hurd almost 9 years
    Note that Linq (or really overload resolution of both C# and VB) will allow a Func<T,bool> where it needs a Predicate<T> but not vice versa: "cannot convert from 'System.Predicate<int>' to 'System.Func<int, bool>'".
  • Mark Hurd
    Mark Hurd almost 9 years
    This means that if you create a Where<T>(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 :-( ).
  • Jon Skeet
    Jon Skeet almost 9 years
    @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<T, bool> or a Predicate<T>, and a reference to an existing Predicate<T>. To call the original extension method, just call it as a static method: Enumerable.Where(...)
  • Mark Hurd
    Mark Hurd almost 9 years
    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".
  • Jon Skeet
    Jon Skeet almost 9 years
    @MarkHurd: It looks like VB creates a new delegate type for situations like that.
  • Mark Hurd
    Mark Hurd almost 9 years
    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.
  • A.B.
    A.B. about 6 years
    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<double> myFoo = new Func<double>(foo); and foo definition could be static double foo(){return 1.0;}
  • MarredCheese
    MarredCheese about 5 years
    @Martin Predicate only takes one parameter.