使用 Func<>(或 Action<>)还是创建自己的委托?

12

在一个方法中的参数类型方面,比如说不涉及到LINQ,那么哪种方式更好呢?显然 Func 更好,因为它更简单,描述性更强,并且如果每个人都使用它,那么所有内容都将变得兼容(好)。

然而我注意到 Microsoft 在一些库中使用了自己的委托,例如事件处理程序。那么,它们各自的优缺点是什么?我应该在什么时候使用它们?

编辑:

  • 显然 Func<> 仅在3.5版本中可用,所以这可能是我看到非 Func 委托的主要原因。还有其他不使用 Func 的原因吗?(例如:来自.NET4的此链接

  • 同样的问题也适用于 Action<>


哪些库?可能是那些库比较老,是在 .Net 3.5 之前开发的(特别是 EventHandler 库)。 - Jahan Zinedine
大多数情况下在事件处理程序中看到,但我也在其他库中看到过,我会尽力回忆。 - Louis Rhys
@Louis Rhys: 等价的,但不是类型安全的。lambda表达式或委托将由编译器正确转换为该委托类型。但是,您无法将Action<x,y,z>实例替换为它。但有办法在运行时进行转换。请参考Delegate.CreateDelegate - leppie
我不能。但是微软本可以使用Action<T1,T2,T3>作为参数类型,而不是BookmarkCallback,这样我们就不需要BookmarkCallback了,对吧? - Louis Rhys
可能是手动声明委托,使用Func<T>或Action<T>?的重复问题。 - nawfal
显示剩余5条评论
5个回答

5

当功能非常明确且输入数量较少时,使用Func<>很有用。

当输入数量较大或意图存在歧义时,使用具有命名参数的委托可以使事情更清晰。


如果输入的数量更多,使用名称为LotsOfInputFunction比使用Func<int, bool, string, Type1, Type2>更难记忆。而且,如果意图不明确,我可以在变量名或参数名中进行澄清,对吧? - Louis Rhys
3
我的意思是每个参数的意图。例如:Func<int,int,string,string> - 仅仅看到这个函数签名很难甚至不可能推断出它的作用。另外,添加一个参数可能意味着需要重构大量代码,并且可能会破坏接口。 - user111013

1

它们在大多数情况下是相同的,除非该方法具有Expression参数。这些需要定义为“lambda”,而不是delegate。当处理IQueryable并获取IEnumerable被调用/解析时,这将会非常棘手(例如LINQ2SQL)。


1

如果在您的情况下确实适用,Func<>和Action<>是首选。运行时会创建程序中使用的每种类型的实例,如果您使用了Func,则意味着已创建该类型的实例。在自定义委托的情况下,事情会有所不同,即使它们本质上与现有委托相似,也会创建新类型。

然而,有时自定义委托可以使代码更清晰。


1
然而我注意到微软在一些库中使用了自己的委托,例如事件处理程序。那么,它们各自的优缺点是什么?我应该在什么时候使用它们呢?
其中一部分是历史遗留问题:在C#3/.NET3之前定义的API,当添加Action<>和Func<>时。对于事件,EventHandler是更好的选择,因为它强制执行正确的约定。

这是来自.NET 4的内容:此链接 - Louis Rhys
1
@Louis...在WF4的其他地方使用了Func<>,所以这很奇怪。这是一个在一致性审查中被忽略的问题吗? - Richard

0

您可以创建一个类,将n个输入作为类属性保存,并将该类的对象作为单个输入传递给func<>委托。


这个回答如何解决问题? - Louis Rhys

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接