函数vs.动作vs.谓词

通过真实的例子和它们的使用,有人能帮助我理解:

  1. 我们什么时候需要Func<T, ..>代表?
  2. 我们什么时候需要Action<T>代表?
  3. 我们什么时候需要Predicate<T>代表?
419470 次浏览

FuncAction之间的区别只是您是否希望委托返回值(使用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>的一个特殊情况,在所有FuncAction代表出现之前引入。我怀疑如果我们已经有了FuncAction的各种伪装,Predicate就不会被引入……尽管确实赋予了委托的使用一定的意义,而FuncAction用于广泛不同的目的。

PredicateList<T>中主要用于FindAllRemoveAll等方法。

Func-当您想要一个可能接受也可能不接受参数并返回值的函数的委托时。最常见的例子是从LINQ中选择:

var result = someCollection.Select( x => new { x.Name, x.Address });

行动-当您想要一个函数的委托时,该函数可能会或可能不会接受参数并且不返回值。我经常将这些用于匿名事件处理程序:

button1.Click += (sender, e) => { /* Do Some Work */ }

谓词-当您想要一个专门版本的Func时,它根据一组标准评估一个值并返回一个布尔结果(匹配为真,否则为假)。

var filteredResults =someCollection.Where(x => x.someCriteriaHolder == someCriteria);

我只是仔细检查了一下,结果发现LINQ不使用谓词。不知道他们为什么做出这个决定……但理论上这仍然是一个谓词适合的情况。

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

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

谓词是一种特殊的Func,通常用于比较(接受泛型参数并返回bool)。

虽然与Linq一起广泛使用,但Action和Func是逻辑上独立于Linq的概念。C++已经包含了类型化函数指针形式的基本概念。

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

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