Delegates: Predicate VS. Action VS. Func

Func vs. Action vs. Predicate

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.

Delegates: Predicate vs. Action vs. Func


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

differences between Predicate and Func delegate in C#

Predicate<T> was introduced in .NET 2.0 with the introduction of generics. It's a delegate taking one parameter and returning a bool.

However, with the introduction of LINQ in .NET 3.5, a need was identified for two families of generic types - Func and Action (the difference being on whether they return anything) taking up to 16 41 generic input parameters and being generic in their return types. If Func had existed first, Predicate<T> would never have been created in the first place. It's an unnecessarily specialized delegate type.

For backwards compatibility reasons though, they cannot now remove Predicate<T> from the framework. Some may argue that its name does convey specific semantic meaning but I'd struggle to identify many situations where any Func<T,bool> (or Func<T1,T2,bool>, etc.) wouldn't be considered a predicate.


14 in .NET 3.5, 16 in .NET 4 and later.

Delegates vs Action, Func in C#

None of the Func or Action types allow out or ref parameters, so you'll have to define your own delegates if you need to use those e.g.:

public delegate bool TryParse<T>(string s, out T value);

Action, Func and Predicate delegates - C#

Predicate<T> is a delegate that takes a T and returns a bool.

It's completely equivalent to Func<T, bool>.

The difference is that Predicate<T> was added in .Net 2.0, whereas all of the Func<*> delegates were added in .Net 3.5. (except the ones with >8 parameters, which were added in .Net 4.0)

The LINQ-like methods in List<T> (FindAll(), TrueForAll(), etc) take Predicate<T>s.

To answer your second question, void cannot be used as a generic parameter.

(Func, Action, Predicate) VS Converter and Comparison delegate c#


Now I'm confused in Converter and Comparison delegate,why .Net Framework introduced these 2 delegate flavours for just converting and comparing, when and how to use these 2 over existing 3.

Historically, the delegates were introduced in the opposite order to the order your question suggests.

Predicate<T>, Converter<TInput, TOutput> and Comparison<T> were introduced in .NET 2.0. They were used by List<T> and a few other types. At this point in time C# didn't support lambda expressions but did support anonymous methods. Delegates were mostly used for event handling and starting threads... supporting them for predicates, conversion and comparison was a baby step, effectively.

Note that Predicate<T> isn't used for comparisons - it's used for testing a single value. For example, you could have a Predicate<string> for "Is the string length more than 5 characters?" Comparison<T>, however, is for comparing values - it's used for sorting.

The Func and Action delegates were (mostly - Action<T> was in .NET 2.0; used by List<T>.ForEach) introduced in .NET 3.5, with LINQ. That was the time frame in which C# 3 introduced lambda expressions and its LINQ support as well, and suddenly delegates were everywhere. I believe the level of awareness of delegates (and how they could be used) went up massively with C# 3.

Early pre-releases of LINQ used Predicate<T> instead of Func<T, bool>, but then additional overloads of Where were introduced accepting Func<T, int, bool> to allow the index to be part of the predicate.

I suspect that if the framework were redesigned from scratch, the "special purpose" delegates (Predicate<T>, Converter<TInput, TOutput> and Comparison<T>) might not exist. It's possible that Predicate<T> and Comparison<T> would still exist, as they provide additional semantic hints as to the purpose of the delegate which can help readability - but Converter<TInput, TOutput> really doesn't have any benefits over Func<T, TResult>.

When to use Action Delegate instead of Predicate Delegate

Predicate delegate as the name says constitutes a Predicate which would match a condition/predicate and return bool. Where as Action delegate as the signature says doesn't return anything (one way work).

List<string>.RemoveAll() requires a predicate cause, what if you want to remove all element T from list which matches a specific condition?

When to use Action Delegate instead of Predicate Delegate

Predicate delegate as the name says constitutes a Predicate which would match a condition/predicate and return bool. Where as Action delegate as the signature says doesn't return anything (one way work).

List<string>.RemoveAll() requires a predicate cause, what if you want to remove all element T from list which matches a specific condition?

When are delegates and Func/Action not interchangeable?

As Jon Skeet answered in the comments, I was missing the fact that Action/Func are literally delegates (I thought it was classes encapsulating delegates) :

namespace System
{
public delegate TResult Func<in T, out TResult>(T arg);
}

So there's no difference between delegates and corresponding Func/Action because Func/Action are delegates.



Related Topics



Leave a reply



Submit