Func vs. Action vs. Predicate

Inf*_*ner 703 c# delegates

通过实例和它们的使用,有人可以帮助我理解:

  1. 我们什么时候需要Func委托?
  2. 我们什么时候需要行动委托?
  3. 我们什么时候需要Predicates委托?

Jon*_*eet 885

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

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

 list.Select(x => x.SomeProperty)
Run Code Online (Sandbox Code Playgroud)

或过滤:

 list.Where(x => x.SomeValue == someOtherValue)
Run Code Online (Sandbox Code Playgroud)

或关键选择:

 list.Join(otherList, x => x.FirstKey, y => y.SecondKey, ...)
Run Code Online (Sandbox Code Playgroud)

Action更常用于以下内容List<T>.ForEach:对列表中的每个项执行给定操作.我用这个少往往比Func,虽然我有时使用无参数的版本,喜欢的东西Control.BeginInvokeDispatcher.BeginInvoke.

PredicateFunc<T, bool>真的只是一个特殊的套装,在所有代表Func和大多数Action代表出现之前介绍过.我怀疑,如果我们已经拥有Func并且Action以各种形式出现,Predicate那么就不会被引入......尽管它确实赋予代表使用某种意义,但是Func并且Action用于广泛不同的目的.

Predicate主要用于List<T>FindAll和的方法RemoveAll.

  • 我更喜欢在函数签名中看到`Predicate`.它说明了传递的方法做出决定而不仅仅是返回成功代码或不同类型的`bool`. (66认同)
  • 有没有关于是否更喜欢'Predicate <T>`或`Func <T,bool>`的设计指南?我喜欢"谓词"的表现力,但我也看到了对"Func"的推荐. (6认同)
  • 我有点像你解释它的简单.func - 返回动作 - 执行(方法) (6认同)
  • @Ron:是的,这几乎是我倒数第二段的内容. (5认同)
  • @CodeInChaos:不是我见过的.LINQ始终使用`Func`,但这可能是为了保持一致性,因为许多接受`Func <T,bool>`作为谓词的方法也有一个带有索引谓词的`Func <T,int,bool>`的重载. (5认同)
  • @JonSkeet,是的,但是你的倒数第二段读起来就像是事情发生了怎么样的历史,把这个意图隐藏在它的中间,让它看起来像一个非评论.@Ron的评论很清楚,它是一种理想的效果(不仅仅是软件演化的副产品),并指出有意选择在一些用例中使用`Predicate`s和`Func <...,bool >在其他人中传达意义._巧合的是,可以说你的倒数第二段与@ Ron的评论之间的区别就像使用`Func <T,bool>`和`Predicate <T>`之间的区别. (2认同)

Kna*_*bax 353

Action是方法的委托(指针),它接受零个,一个或多个输入参数,但不返回任何内容.

Func是方法的委托(指针),它接受零个,一个或多个输入参数,并返回一个值(或引用).

谓词是一种特殊的Func,经常用于比较.

虽然广泛用于Linq,但Action和Func在概念上与Linq无关.C++已经包含了类型化函数指针形式的基本概念.

这是Action和Func的一个小例子,不使用Linq:

class Program
{
    static void Main(string[] args)
    {
        Action<int> myAction = new Action<int>(DoSomething);
        myAction(123);           // Prints out "123"
                                 // can be also called as myAction.Invoke(123);

        Func<int, double> myFunc = new Func<int, double>(CalculateSomething);
        Console.WriteLine(myFunc(5));   // Prints out "2.5"
    }

    static void DoSomething(int i)
    {
        Console.WriteLine(i);
    }

    static double CalculateSomething(int i)
    {
        return (double)i/2;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • Predicate是一个委托,它接受泛型参数并返回bool (32认同)
  • 很好的例子!请注意,您也可以通过调用它来调用myAction:`myAction(123);`.你不需要使用`.Invoke()` (27认同)
  • @Martin Predicate 只接受一个参数。 (2认同)

Jus*_*ner 65

Func - 当您想要一个函数的委托时,该函数可能会也可能不会获取参数并返回一个值.最常见的例子是从LINQ中选择:

var result = someCollection.Select( x => new { x.Name, x.Address });
Run Code Online (Sandbox Code Playgroud)

操作 - 当您希望某个函数的委托可能带有或不带参数但不返回值时.我经常将它们用于匿名事件处理程序:

button1.Click += (sender, e) => { /* Do Some Work */ }
Run Code Online (Sandbox Code Playgroud)

谓词 - 当你想要一个特殊版本的Func,它根据一组条件评估一个值并返回一个布尔结果(匹配为true,否则为false).同样,这些在LINQ中经常用于像Where这样的东西:

var filteredResults = 
    someCollection.Where(x => x.someCriteriaHolder == someCriteria);
Run Code Online (Sandbox Code Playgroud)

我只是仔细检查,结果是LINQ不使用Predicates.不确定他们为什么做出这个决定......但理论上它仍然是谓词适合的情况.

  • 我知道这是旧的,但LINQ没有使用Predicate,因为它早于我们今天所知的Func和Action,而后两个可以用来以更好的方式实现完全相同的结果. (2认同)
  • 这取决于你如何使用委托,但有时名称不是那么重要,只是为了一次使用而创建函数和变量会降低可读性. (2认同)