【问题标题】:Func vs. Action vs. Predicate [duplicate]Func vs. Action vs. Predicate [重复]
【发布时间】:2011-05-18 01:52:31
【问题描述】:

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

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

【问题讨论】:

  • 尽管这是重复的,但它有一个更彻底的接受答案
  • @reggaeguitar 有趣的是,两个被接受的答案都来自 Jon Skeet
  • 深入阅读 Jon Skeet 的书 C# 将我带到了这里。谈论起步。

标签: c# delegates action func


【解决方案1】:

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

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

【讨论】:

  • Predicate 是一个接受泛型参数并返回 bool 的委托
  • 很好的例子!请注意,您也可以通过简单地调用 myAction 来调用它:myAction(123);。你不需要使用.Invoke()
  • 为了完整起见,如果您想使用不带参数但返回值(或引用)的 Func,您应该编写类似这样的内容 Func myFoo = new Func( foo); 和 foo 定义可以是 static double foo(){return 1.0;}
  • @Martin Predicate 只接受一个参数。
【解决方案2】:

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

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

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

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

谓词 - 当您想要一个专门版本的 Func 时,它根据一组标准评估一个值并返回一个布尔结果(匹配时为 true,否则为 false)。 同样,这些在 LINQ 中经常用于诸如 Where:

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

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

【讨论】:

  • 我知道这是旧的,但 LINQ 没有使用 Predicate,因为它早于我们今天所知道的 Func 和 Action,而后两者可用于实现完全相同的结果,效果要好得多方式。
  • @gparent,为什么更好?我认为使用有意义命名的委托而不是 Func 或 Action 时可读性更好。
  • 这取决于你如何使用委托,但有时名称并不那么重要,而且我必须创建函数和变量只是为了一种用途会降低可读性。
【解决方案3】:

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&lt;T&gt;.ForEach 之类的事情:对列表中的每个项目执行给定的操作。我使用它的频率低于Func,尽管我确实有时将无参数版本用于Control.BeginInvoke 和Dispatcher.BeginInvoke 之类的东西。

Predicate 实际上只是一个特殊的 Func&lt;T, bool&gt;,在所有 Func 和大多数 Action 代表出现之前引入。我怀疑如果我们已经有了 Func 和 Action 的各种伪装,Predicate 就不会被引入......尽管它确实赋予了使用一定的意义代表,而Func 和Action 用于广泛不同的目的。

Predicate 主要用于List&lt;T&gt; 中,用于FindAll 和RemoveAll 等方法。

【讨论】:

  • 我更喜欢在函数签名中看到Predicate。它说明传递的方法做出决定,而不仅仅是返回成功代码或不同类型的bool。
  • 是否有任何设计指南来选择Predicate&lt;T&gt; 还是Func&lt;T,bool&gt;?我喜欢Predicate 的表现力,但我也看到了Func 的推荐。
  • @Ron:是的,这几乎就是我倒数第二段的内容。
  • @CodeInChaos:我没见过。 LINQ 始终使用Func,但这可能是为了保持一致性,因为许多接受Func&lt;T,bool&gt; 作为谓词的方法也有一个重载,将Func&lt;T,int,bool&gt; 作为索引谓词。
  • 我有点喜欢你解释它的简单程度。 func - 返回动作 - 执行(方法)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-07-07
  • 2010-11-10
  • 2010-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-09
相关资源
最近更新 更多