c# - Action/Func vs Methods,有什么意义?

标签 c# .net function action func

我知道如何在 .NET 中使用 ActionFunc,但每次我开始使用时,都可以使用常规的旧方法实现完全相同的解决方案我调用。

这不包括 ActionFunc 用作我无法控制的参数的情况,例如 LINQ 的 .Where

所以基本上我的问题是......为什么这些存在?它们能给我带来哪些简单方法无法提供的额外和新鲜体验?

最佳答案

我认为这里的其他答案谈论的是 Action。/Func是及其用途。我将尝试回答如何在 Action 之间进行选择/Func和方法。首先是区别:

1) 从原始性能的角度来看,delegates are slower compared to direct method calls , 但它是如此微不足道以至于担心它是一种不好的做法。

2) 方法可以有重载(具有不同签名的相同函数名称)但不能 Action/Func委托(delegate),因为它们被声明为变量,并且根据 C# 规则,在给定范围内不能有两个具有相同名称的变量。

bool IsIt() { return 1 > 2; }
bool IsIt(int i) { return i > 2; } //legal

Func<bool> IsIt = () => 1 > 2; 
Func<int, bool> IsIt = i => i > 2; //illegal, duplicate variable naming

3) 因此,Action/Func是可重新分配的,可以指向任何函数,而方法一旦编译就永远保持不变。使用 Func/Action 在语义上是错误的如果它指向的方法在运行时永远不会改变。

bool IsIt() { return 1 > 2; } //always returns false

Func<bool> IsIt = () => 1 > 2; 
IsIt = () => 2 > 1; //output of IsIt depends on the function it points to.

4) 可以指定ref/out普通方法的参数。例如,您可以拥有

bool IsIt(out string p1, ref int p2) { return 1 > 2; } //legal

Func<out string, ref int, bool> IsIt; //illegal

5) 您不能为 Action 引入新的泛型类型参数/Func (顺便说一句,它们已经是通用的,但类型参数只能是已知类型或在父方法或类中指定的类型),与方法不同。

bool IsIt<A, R>() { return 1 > 2; } //legal

Func<bool> IsIt<A, R> = () => 1 > 2; //illegal

6) 方法可以有可选参数,不是Action/Func .

bool IsIt(string p1 = "xyz") { return 1 > 2; } //legal

Func<string, bool> IsIt = (p1 = "xyz") => 1 > 2; //illegal

7) 你可以拥有params方法参数的关键字,而不是 Action/Func .

bool IsIt(params string[] p1) { return 1 > 2; } //legal

Func<params string[], bool> IsIt = p1 => 1 > 2; //illegal

8) Intellisense 可以很好地处理方法的参数名称(因此您可以为方法提供很酷的 XML 文档),而不是 Action/Func .因此,就可读性而言,常规方法胜出。

9) Action/Func有一个参数限制为 16(并不是说你不能用更多的参数定义你自己的)但是 methods support more than you will ever need.

至于什么时候用哪个,我会考虑以下几点:

  1. 当您基于以上任何一点被迫使用一个时,您无论如何都别无选择。 第 3 点是我发现最有说服力的,您必须以此为基础做出决定。

  2. 在大多数正常情况下,常规方法是可行的方法。这是在 C# 和 VB.NET 世界中重构一组通用功能的标准方法。

  3. 根据经验,如果函数不止一行,我更喜欢方法。

  4. 如果函数在特定方法之外没有相关性并且函数太琐碎,例如简单的选择器 (Func<S, T>) 或谓词 (Func<bool>),我更喜欢 Action/Func .例如,

    public static string GetTimeStamp() 
    {
        Func<DateTime, string> f = dt => humanReadable 
                                       ? dt.ToShortTimeString() 
                                       : dt.ToLongTimeString();
        return f(DateTime.Now);
    }
    
  5. 在某些情况下 Action/Func更有意义。例如,如果您必须构建一个繁重的表达式并编译一个委托(delegate),那么值得只做一次并缓存已编译的委托(delegate)。

    public static class Cache<T> 
    { 
        public static readonly Func<T> Get = GetImpl();
    
        static Func<T> GetImpl()
        {
            //some expensive operation here, and return a compiled delegate
        }
    }
    

    代替

    public static class Cache<T> 
    {
        public static T Get()
        {
            //build expression, compile delegate and invoke the delegate
        }
    }
    

    在第一种情况下,当您调用 Get , GetImpl只执行一次,在第二种情况下,(昂贵的)Get每次都会被调用。


不要忘记匿名方法本身会有certain limitsFunc/Action无关,使使用略有不同。另见 this for a related question.

关于c# - Action/Func vs Methods,有什么意义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7630538/

相关文章:

c# - 文本框如何作为 IP 地址框

.net - 多重触发的否定或非条件元素

c# - iTextSharp 重用嵌入在 Acrofield 中的字体

php - 如何获取 PHP 类中所有函数的数组?

c - C函数中的多维char数组

javascript - 为什么我的程序不将变量分配给对象,然后根据它进行计算?

c# - WPF 复杂验证

c# - 为什么 ListView 只显示 12 个项目?

c# - 如果c# wpf中的可见性为 'Auto',如何知道 ListView 的VerticalScrollbar是否可见?

c# - 使用正则表达式读入文件?