150

Can someone provide a good explanation (hopefully with examples) of these 3 most important delegates:

  • Predicate
  • Action
  • Func
Andrew
  • 16,273
  • 10
  • 93
  • 104

9 Answers9

191
  • Predicate: essentially Func<T, bool>; asks the question "does the specified argument satisfy the condition represented by the delegate?" Used in things like List.FindAll.

  • Action: Perform an action given the arguments. Very general purpose. Not used much in LINQ as it implies side-effects, basically.

  • Func: Used extensively in LINQ, usually to transform the argument, e.g. by projecting a complex structure to one property.

Other important delegates:

  • EventHandler/EventHandler<T>: Used all over WinForms

  • Comparison<T>: Like IComparer<T> but in delegate form.

Jon Skeet
  • 1,335,956
  • 823
  • 8,931
  • 9,049
  • 3
    There's also `System.Converter`, though it's rarely used. – G-Wiz Jan 04 '10 at 23:03
  • 4
    The Converter is a nice delegate when a lot of Converting of Model into Business classes is needed, i.e. http://www.stum.de/2009/12/23/using-a-converter-to-convert-from-a-model-to-a-business-class/ – Michael Stum Jan 07 '10 at 20:52
  • `EventHandler/EventHandler` appear all over outside of WinForms too. – Andy Aug 21 '15 at 12:58
  • @Andy: Somewhat... But less so in WPF for example. I agree that there's nothing WinForms-specific to it. – Jon Skeet Aug 21 '15 at 18:41
65

Action, Func and Predicate all belong to the delegate family.

Action : Action can take n input parameters but it returns void.

Func : Func can take n input parameters but it will always return the result of the provided type. Func<T1,T2,T3,TResult>, here T1,T2,T3 are input parameters and TResult is the output of it.

Predicate : Predicate is also a form of Func but it will always return bool. In simple words it is wrapper of Func<T,bool>.

InteXX
  • 5,576
  • 6
  • 37
  • 62
Rahul Garg
  • 3,825
  • 31
  • 30
10

In addition to Jon's answer, there is also

  • Converter<TInput, TOutput>: It's essentially Func<TInput, TOutput>, but with semantics. Used by List.ConvertAll and Array.ConvertAll, but personally haven't seen it anywhere else.
G-Wiz
  • 7,309
  • 1
  • 33
  • 47
7

A simple example about the arguments and what retutn each type

This Func take two int arguments and return an int.Func always has return type

 Func<int, int, int> sum = (a, b) => a + b;
 Console.WriteLine(sum(3, 5));//Print 8

In this case func doesn't have arguments but return a string

Func<string> print = () => "Hello world";
Console.WriteLine(print());//Print Hello world

This Action take two int arguments and return void

Action<int, int> displayInput = (x, y) => Console.WriteLine("First number is :" + x + " , Second number is "+ y);
displayInput(4, 6); //Print First number is :4 , Second number is :6

This Predicate take one argument and always return bool.Generally Predicates always return bool.

Predicate<int> isPositive = (x) => x > 0;
Console.WriteLine(isPositive(5));//Print True
4

MethodInvoker is one which WinForms developers may use; it accepts no arguments and returns no results. It predates Action, and is still often used when invoking onto the UI thread since BeginInvoke() et al accept an untyped Delegate; although Action will do just as well.

myForm.BeginInvoke((MethodInvoker)delegate
{
  MessageBox.Show("Hello, world...");
});

I'd also be aware of ThreadStart and ParameterizedThreadStart; again most people will substitute an Action these days.

Erik Philips
  • 51,408
  • 11
  • 123
  • 146
El Zorko
  • 3,179
  • 2
  • 25
  • 33
3

Action

Documentation:

Encapsulates a method that has no parameters and does not return a value.

Functions passed using the Action type must return void, and can accept from 0 to 16 parameters.
Action is commonly used when you want a function that can use each element in a container for something, or as callbacks.

public void DoSomething(List<string> lines, Action<string> action)
{
    foreach (string str in lines)
    {
        action(str);
    }
}

Func

Documentation:

Encapsulates a method that has no parameters and returns a value of the type specified by the TResult parameter.

Functions passed using the Func type accept from 0 to 16 parameters, and return any type that isn't void.
Func is commonly used when you want a function that can modify or perform some kind of operation on each element in a container.

//                                                 Parameter Types
//                                                     ▼▼▼  ▼▼▼
public List<int> DoMath(List<(int, int)> numbers, Func<int, int, int> operation)
//                                                               ▲▲▲
//                                                           Return Type
{
    List<int> results = new();
    foreach (var (left, right) in numbers)
    {
        out.Add(operation(left, right));
    }
    return out;
}

Predicate

Documentation:

Represents the method that defines a set of criteria and determines whether the specified object meets those criteria.

Functions passed with the Predicate type must return a bool, and must accept exactly 1 parameter.

An example of functions that accept Predicates are LINQ functions like All & Any, which return true if the supplied predicate returns true for all/any of the elements in a list.

public void Example(string str)
{
    // The char.IsLetter() function can be used as a predicate
    //   because it takes 1 char as a parameter, and returns a bool.
    //          ▼▼▼▼▼▼▼▼▼▼▼▼▼
    if (str.All(char.IsLetter))
    {
        Console.WriteLine("All characters in the string are letters.");
    }
}

Comparison

Type Return Type Min Parameters Max Parameters
Action void 0 16
Func Any type that isn't void 0 16
Predicate bool 1 1

The only differences between Action, Func, and Predicate are the types that they return & accept as parameters; they are all delegates and as such they all represent a function passed as a parameter.

You can make your own delegate types in 1 line of code, and use them in the same way as the premade ones.

//         Accepts functions that return a decimal type, and...
//              ▼▼▼▼▼▼▼
public delegate decimal Operation(decimal left, decimal right);
//                                ▲▲▲▲▲▲▲       ▲▲▲▲▲▲▲
//                    ...take 2 parameters, both of type decimal.

You can read more about delegates here:
https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/delegates/

jocolley
  • 31
  • 4
3

Predicate, Func and Action are inbuilt delegate instances of .NET. Each of these delegate instances could refer or point to user methods with specific signature.

Action delegate - Action delegate instances could point to methods that take arguments and returns void.

Func delegate - Func delegate instance could point to method(s) that take variable number of arguments and return some type.

Predicate - Predicates are similar to func delegate instances and they could point to methods that take variable number of arguments and return a bool type.

IntelligentBinary
  • 552
  • 1
  • 6
  • 14
2

Action and Func with lambda:

person p = new person();
Action<int, int> mydel = p.add;       /*(int a, int b) => { Console.WriteLine(a + b); };*/
Func<string, string> mydel1 = p.conc; /*(string s) => { return "hello" + s; };*/
mydel(2, 3);
string s1=  mydel1(" Akhil");
Console.WriteLine(s1);
Console.ReadLine();
Pang
  • 9,073
  • 146
  • 84
  • 117
2

Func is more LINQ friendly, can be passed in as a parameter. (point-free)

Predicate cannot, has to be wrapped again.

Predicate<int> IsPositivePred = i => i > 0;
Func<int,bool> IsPositiveFunc = i => i > 0;

new []{2,-4}.Where(i=>IsPositivePred(i)); //Wrap again

new []{2,-4}.Where(IsPositivePred);  //Compile Error
new []{2,-4}.Where(IsPositiveFunc);  //Func as Parameter
Rm558
  • 3,807
  • 3
  • 32
  • 40