我知道如何在 .NET 中使用 Action
和 Func
,但每次我开始使用时,都可以使用常规的旧方法实现完全相同的解决方案我调用。
这不包括 Action
或 Func
用作我无法控制的参数的情况,例如 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.
至于什么时候用哪个,我会考虑以下几点:
当您基于以上任何一点被迫使用一个时,您无论如何都别无选择。 第 3 点是我发现最有说服力的,您必须以此为基础做出决定。
在大多数正常情况下,常规方法是可行的方法。这是在 C# 和 VB.NET 世界中重构一组通用功能的标准方法。
根据经验,如果函数不止一行,我更喜欢方法。
如果函数在特定方法之外没有相关性并且函数太琐碎,例如简单的选择器 (
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); }
在某些情况下
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 limits与Func/Action
无关,使使用略有不同。另见 this for a related question.
关于c# - Action/Func vs Methods,有什么意义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7630538/