Action,Func和Predicate委托 - C#

时间:2013-01-01 13:31:03

标签: c# .net wpf mvvm delegates

我正在尝试理解Action<T>, Func<T> and Predicate<T>代表之间的差异,这是我的WPF / MVVM学习的一部分。

我知道Action<T> and Func<T>只有0到1 +参数,只有Func<T>会返回一个值而Action<T>则没有。

关于Predicate<T> - 我不知道。

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

  1. Predicate<T>做什么? (欢迎举例!)
  2. 如果Action<T>返回没有,那么仅使用void会不会更简单? (或任何其他类型,如果我们正在讨论Func<T>。)
  3. 我希望您在问题中避免使用LINQ / List示例 我已经看过那些但是它们只是让它变得更加混乱,因为让我对这些代表感兴趣的代码与它无关(我想!)。 因此,我想使用我熟悉的代码来获得我的答案。

    这是:

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

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

    任何帮助表示赞赏!谢谢! :)

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

6 个答案:

答案 0 :(得分:9)

Predicate<T>是一个代理人,他需要T并返回bool
它完全等同于Func<T, bool>

不同之处在于。{2.0}中添加了Predicate<T>,而在.Net 3.5中添加了所有Func<*>代理。 (除了带有&gt; 8参数的那些,在.Net 4.0中添加)

List<T>FindAll()TrueForAll()等)中类似LINQ的方法采用Predicate<T> s。

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

答案 1 :(得分:1)

  

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

必须返回boolean,并在条件结构中使用。它等同于{but not assignable)到Func<T, bool>Predicate is mostly used in List for methods like FindAll and RemoveAll.

Action<T> vs Func<T,bool>

您无法将函数返回void Func<void, T>。因此Action<T>是必需的。 generics无法使用Void类型。

答案 2 :(得分:1)

  

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

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

  

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

Action被定义为返回void的委托。在这里,人们可能会争论为什么会有两种代表,但这只是设计的结果。另一种方法是让Func返回无效的Unit

答案 3 :(得分:1)

Func<T,bool> and Predicate<T> 

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

答案 4 :(得分:0)

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

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

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


编辑:检查一下 - Why Func<T,bool> instead of Predicate<T>?

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

答案 5 :(得分:-1)

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<T>等内容。

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

我使用此频率的频率低于Func,但有时我会使用无参数版本来处理Control.BeginInvokeDispatcher.BeginInvoke等内容。

Predicate只是一个特殊的Func<T, bool>,在所有Func和大多数Action代表出现之前就已经介绍过了。我怀疑,如果我们已经有FuncAction各种伪装,Predicate就不会被引入......尽管它确实赋予了使用delegate,而FuncAction用于广泛不同的目的。

Predicate主要用于List<T>,用于FindAllRemoveAll等方法。