繁体   English   中英

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

[英]Why don't Funcs accept more than 16 arguments?

由于 Javascript 是我最精通的语言,所以我熟悉使用函数作为一等对象。 我原以为 C# 缺少这个功能,但后来我听说了FuncActiondelegate ,我认为它们非常棒。

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

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

我注意到当你打字时

Func<

IntelliSense 显示它有 17 个重载:

delegate System.Func<out TResult>
delegate System.Func<in T, out TResult>
delegate System.Func<in T1, in T2, out TResult>
...snip...
delegate System.Func<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13, in T14, in T15, in T16, out TResult>

那让我发笑。 我查看了FuncMSDN 文档,然后又笑了。 这让我尝试声明一个带有 17 个参数的Func 它会导致错误( Using the generic type 'System.Func<TResult>' requires 1 type arguments )。

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

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

你希望像 C# 缺少的可变参数类型参数 C# 需要固定泛型类型的数量,因此FuncActionTuple类型的数量令人发指。

如果您正在购买语言,此功能是在 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<P, R>(params P[] parameters);

然后像这样使用它:

ArrayFunc<int, int> 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);

这是该语言的一个非常灵活和强大的特性。

我想我明白 - 你可以用 JavaScript 和函数(参数)做什么是非常整洁的,但它也不是静态类型的。

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

当然,这在 C# 中是错误的:

Func<A1,Func<A2,Func<A3,...<Func<An,Result>>...> 
  x1 =>
    (x2 => 
      (x3 => 
        ... 
          (xn => 
              { /*return soomething */ }
  ))...);

但这就是 F# 的用途 ;) 当然,无论如何你都不应该创建一个参数超过几个(远低于 16!)的函数。

您可以使用超过 16 个参数创建自己的委托。 或者您可以使用Tuple<T1, T2, T3, T4, T5, T6, T7, TRest> (或任何其他数据结构)作为参数。

Why is there a limit anyway?

有意见认为函数可能不应该有超过 3 个参数。 如果它有更多,它变得越来越难以理解。 当然这可能不是 C# 中会这样的原因,但这种限制终究不是什么坏事。

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

多亏了 BCL 团队,System.Func 委托才可能存在。他们意识到包含有限数量的预定义泛型委托会很方便(甚至在很多情况下都需要)。

要按照您说的去做.. 即 Func 委托的无限数量的泛型参数需要更改语言.. c# 和 vb.net 团队(以及其他可能的团队)都有责任更改语言以允许这样做。

也许,在某些时候,如果此功能的好处超过预定义少数 Func 委托的成本,并且这比其他语言更改更重要(并且它不是破坏性更改),那么相关团队将实现无限的通用参数.. 可能不会有一段时间了!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM