Action,Func和Predicate委托 – C#

我试图理解Action, Func and Predicate委托之间的差异,作为我的WPF / MVVM学习的一部分。

我知道Action and Func都采用零到一个+参数,只有Func返回一个值,而Action则没有。

至于Predicate – 我不知道。

因此,我提出了以下问题:

  1. Predicate做什么? (欢迎举例!)
  2. 如果Action 什么都不返回,那么仅使用void会不会更简单? (或任何其他类型,如果它是我们正在讨论的Func 。)

我希望你在问题中避免使用LINQ / List示例。
我已经看过那些但是它们只是让它变得更加混乱,因为让我对这些代表“感兴趣”的代码与它无关(我想!)。
因此,我想使用我熟悉的代码来获得我的答案。

这里是:

 public class RelayCommand : ICommand { readonly Action _execute; readonly Predicate _canExecute; public RelayCommand(Action execute) : this(execute, null) { } public RelayCommand(Action execute, Predicate 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); } } 

注意:
我拿出评论来避免超长代码块。
完整的代码可以在这里找到。

任何帮助表示赞赏! 谢谢! 🙂

PS:请不要指我其他问题。 我确实尝试搜索,但我找不到任何简单的东西让我理解。

Predicate是一个代表,它接受一个T并返回一个bool
它完全等同于Func

区别在于Predicate是在.Net 2.0中添加的,而所有Func<*>代表都是在.Net 3.5中添加的。 (除了具有> 8个参数的那些,在.Net 4.0中添加)

ListFindAll()TrueForAll()等中类似LINQ的方法采用Predicate

要回答第二个问题, void不能用作通用参数。

Predicate做什么? (欢迎举例!)

谓词是一个函数,它接受一个参数并返回bool,例如x > 20

如果Action没有返回任何内容,那么仅使用void会不会更简单? (或任何其他类型,如果它是我们正在讨论的Func。)

Action被定义为返回void的委托。 在这里,人们可能会争论为什么有两种代表,但这只是设计的结果。 另一种方法是使Func返回不执行任何操作的Unit

Predicate做什么? (欢迎举例!)

它必须返回boolean ,并在条件结构中使用。 它与Func等效( 但不可分配 )。 对于像FindAll和RemoveAll这样的方法,谓词主要用在List中。

Action vs Func

你不能表示一个函数返回void作为Func 。 所以Action是必需的。 Void类型不能用于generics 。

 Func and Predicate 

往往是同一个代表。 但谓词是传统的,因为谓词是一个委托类型,从一开始就没有Func或Action。 如果您将看到像Array,List这样的类的FindAll / Find方法,他们使用Predicate.Predicates只返回bool但Func可以返回您指定的任何类型,因此bool也会出现。

Predicate是一个委托,它接受一个T并返回一个布尔值,本质上它是一个过滤函数。 或者这就是你将主要使用它。

如果您使用Linq的Where()扩展方法,您将看到它接收Predicate委托作为参数,您也可以使用Predicates创建更复杂的过滤方法作为表达式,并动态组合多个Predicate委托与它们之间的AND或OR条件等等。

例如,我需要在WPF中构建一个Report页面,用户可以动态选择多个参数来自定义Report页面的内容,在这种情况下,我为所选的过滤选项创建了Predicates(日期时间间隔,布尔值,必须的某些字符串)包含在选定的字段等中)然后组合谓词并将它们编译成一个表达式,我后来用它来过滤我向用户显示的数据集合。


编辑:检查这个 – 为什么Func 而不是Predicate

简而言之:编码指南声明不再使用Predicates而是使用Func

Func和Action之间的区别仅在于您是希望委托返回值(使用Func)还是不使用(使用Action)。

Func可能是LINQ中最常用的 – 例如在投影中:

 list.Select(x => x.SomeProperty) 

或过滤:

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

或关键选择:

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

Action更常用于List类的东西。

ForEach :为列表中的每个项执行给定的操作。

我使用它比Func更少,尽管我有时会使用无参数版本来控制Control.BeginInvokeDispatcher.BeginInvoke

Predicate只是一个特殊的套装Func真的,在所有Func和大多数Action代表出现之前引入。 我怀疑,如果我们已经有各种伪装的FuncAction ,那么Predicate就不会被引入……虽然它确实赋予delegate使用一定的意义,而FuncAction则被广泛使用目的。

Predicate主要用于List用于FindAllRemoveAll等方法。