Action, Func and Predicate delegates - C# [duplica

2019-04-09 03:00发布

问题:

This question already has an answer here:

  • Delegates: Predicate Action Func 7 answers

I'm trying to understand the differences between the Action<T>, Func<T> and Predicate<T> delegates as part of my WPF/MVVM learning.

I know Action<T> and Func<T> both take zero to one+ parameters, only Func<T> returns a value while Action<T> don't.

As for Predicate<T> - I have no idea.

Therefore, I came up with this following questions:

  1. What does Predicate<T> do? (Examples welcomed!)
  2. If Action<T> returns nothing, wouldn't it be simpler to just use void instead? (Or any other type if it's Func<T> we're talking about.)

I'd like you to avoid LINQ/List examples in your questions.
I've seen those already but they just make it more confusing as the code that got me 'interested' in these delegates have nothing to do with it (I think!).
Therefore, I'd like to use a code I'm familiar with to get my answer.

Here it is:

public class RelayCommand : ICommand
{
    readonly Action<object> _execute;
    readonly Predicate<object> _canExecute;

public RelayCommand(Action<object> execute)
    : this(execute, null)
{
}

public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
    if (execute == null)
        throw new ArgumentNullException("execute");

    _execute = execute;
    _canExecute = canExecute;
}

[DebuggerStepThrough]
public bool CanExecute(object parameters)
{
    return _canExecute == null ? true : _canExecute(parameters);
}

public event EventHandler CanExecuteChanged
{
    add { CommandManager.RequerySuggested += value; }
    remove { CommandManager.RequerySuggested -= value; }
}

public void Execute(object parameters)
{
    _execute(parameters);
}
}

Note:
I took out the comments to avoid super-long block of code.
The full code can be found HERE.

Any help is appreciated! Thanks! :)

P.S: Please don't point me to other questions. I did try to search but I couldn't find anything simple enough for me to understand.

回答1:

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.



回答2:

What does Predicate do? (Examples welcomed!)

Predicate is a function that takes an argument and returns bool e.g x > 20

If Action returns nothing, wouldn't it be simpler to just use void instead? (Or any other type if it's Func we're talking about.)

Action is defined as delegate that returns void. Here one may argue why there are two kind of delegates, but simply that's the outcome of the design. Another approach is to have Func that returns Unit that does nothing.



回答3:

What does Predicate do? (Examples welcomed!)

It must return boolean, and used in conditional constructs. It is equivalent (but not assignable) to Func<T, bool>. Predicate is mostly used in List for methods like FindAll and RemoveAll.

Action<T> vs Func<T,bool>

You cant represent a function returning void as Func<void, T>. So Action<T> is required. Void type cannot be used in generics.



回答4:

Func<T,bool> and Predicate<T> 

tends to the same delegate. But Predicate is Kindof traditional because Predicate was a delegate Type since from beginning when there was no Func or Action. If you will see FindAll/Find method of classes like Array ,List they use Predicate.Predicates return only bool but Func can return any type you specify so bool also comes in that.



回答5:

A Predicate is a delegate that takes a T and returns a boolean, in essence it's a filtering function. Or that is what you will use it for mostly.

If you use Linq's Where() extension method you will see it receives a Predicate delegate as a parameter, also you can use Predicates to create more intricate filtering methods as Expressions and dynamically combine multiple Predicate delegates with AND or OR conditions between them and so forth.

For example i had a requirement to build a Report page in WPF where the user could dynamically select multiple parameters to customize the Report page's content, and in that case i created Predicates for selected filtering options (datetime intervals, booleans, certain strings that must be contained in selected fields etc.) and then combined the predicates and compiled them into an expression that i later used to filter the collection of data i showed the user.


EDIT: Check this - Why Func<T,bool> instead of Predicate<T>?

in short : coding guidelines state to not use Predicates anymore and use Func instead



回答6:

The difference between Func and Action is simply whether you want the delegate to return a value (use Func) or doesn't (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.