为什么Funcs不接受超过16个参数?

由于Javascript是我最熟练的语言,因此我熟悉将函数用作第一类对象。 我原以为C#缺少这个function,但后来我听说FuncAction以及delegate ,我认为这非常棒。

例如,您可以声明一个连接两个字符串的Func ,并在它们之间放置一个空格,如下所示:

 Func concat = (a,b) => a + " " + b; 

当你输入时我注意到了

 Func< 

IntelliSense显示它有17个重载:

 delegate System.Func delegate System.Func delegate System.Func ...snip... delegate System.Func 

那让我开怀大笑。 我查看了Func的MSDN文档并再次笑了起来。 这让我尝试用17个参数声明一个Func 。 它会导致错误( Using the generic type 'System.Func' requires 1 type arguments )。

我同意,拥有一个接受超过16个参数的Func可能不是一个好主意。 即便如此,这似乎是Func实施的一种方式。 它需要记录17个简单的不同重载。 这是它真正需要知道的全部内容:最后一个类型参数是返回类型,并且它之前的所有类型参数都是参数类型。

那么,如果我想创建一个超过16个参数的Func ,我该怎么办? 为什么还有限制? 为什么C#不能让你用任意数量的参数声明一个Func

你希望有类似C#缺乏的可变类型参数 。 C#需要修复generics类型的arity,因此FuncActionTuple类型的可怕扩散。

如果你是语言购物,这个function是在C ++ 11中添加的,但你应该只使用jQuery。 🙂

您只需定义所需的任何委托即可。 因此,具有20个参数的Func将被定义如下:

 public delegate R Func< P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, R>( P0 p0, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9, P10 p10, P11 p11, P12 p12, P13 p13, P14 p14, P15 p15, P16 p16, P17 p17, P18 p18, P19 p19); 

然后你可以像这样使用它:

 Func< int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int> f = ( p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19) => p0 + p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10 + p11 + p12 + p13 + p14 + p15 + p16 + p17 + p18 + p19; var r = f(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); 

C#还允许您在任何委托上使用lambda语法,因此您也可以这样做:

 public delegate R ArrayFunc(params P[] parameters); 

然后像这样使用它:

 ArrayFunc af = ps => ps.Sum(); var ar = af(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); 

它是该语言非常灵活和强大的function。

我想我明白了 – 你可以用JavaScript和函数(参数)做些什么是整洁而且它也不是静态类型的。

但请注意,无论如何,您在函数式编程中永远不需要多个参数。 您可以通过返回另一个函数来链接尽可能多的参数(这是FP中的常见特征,并且通常用于限制JS中可用的技术,但只是稍微弯曲系统)。

当然这在C#中很尴尬:

 Func>...> x1 => (x2 => (x3 => ... (xn => { /*return soomething */ } ))...); 

但这就是F#的用途;)当然,你永远不应该创建一个带有多个参数的函数(低于16的方式!)无论如何。

您可以使用超过16个参数创建自己的委托。 或者您可以使用Tuple (或任何其他数据结构)作为参数。

由于BCL团队,可能会有System.Func代表。他们意识到包含有限数量的预定义通用代表会很方便(甚至在很多情况下都需要)。

要做你说的话…即Func委托的无限数量的通用参数需要语言改变..责任在于c#和vb.net团队(以及其他人可能)改变语言以允许这种情况。

也许,在某些时候,如果这个function的好处超过预定义少数Func代表的成本,这比其他语言更改更重要(并且它不是一个重大变化)相关团队我的工具无限通用参数..可能不会有一段时间了!

Why is there a limit anyway?

有观点认为,function可能不应超过3个参数。 如果它有更多,它变得越来越难以理解。 当然这可能不是C#中这种方式的原因,但毕竟这种限制可能并不是一件坏事。

我认为即使这个16的限制太多了,并且已经鼓励糟糕的设计选择。