C#方法可以定义为采用的最大参数数量是多少?

rmi*_*sen 63 .net c# clr

我试图找出C#中方法可以具有的最大参数数量.我已经到处检查了答案,包括C#官方文档,MSDN和一些CLR参考,我找不到答案.有没有人对这个问题有答案?

rmi*_*sen 66

我使用一次性程序来创建一个程序来确定我可以传递给方法的最大参数数量.根据我的实验结果,我能找到的答案最接近(所有这些仅在我的计算机上有效):

  1. 包含具有16383参数的方法的.net应用程序可以编译,运行和调用(!)
  2. 可以编译包含16384或更多参数的.net应用程序,但运行此类程序会引发未声明的异常.
  3. 也可以编译包含50000个参数的.net应用程序,但尝试运行此类应用程序会导致抛出StackOverflowException.
  4. 尝试编译包含100000个或更多参数的.net应用程序会导致csc.exe发出编译时错误,指出生成的表达式太长或太复杂而无法处理.

除此之外,有没有人对这个问题有明确的答案?

PS如果有人想在他们的计算机上尝试这个实验,你可以从我的测试程序开始,可以下载https://docs.google.com/open?id=0B1Q3uRTkbsXic2cwUFpXanNkSk0

  • 这些数字取决于操作系统的体系结构和计算机的内存. (15认同)
  • 0-16383总共有16384(2 ^ 14)个状态,或者恰好是14位.正如扩展的笑话所说,这是计算机科学中的两个难题之一:缓存失效,命名事物和逐个错误.:) (5认同)
  • 我觉得内存会受到传递给函数的值参数数量以及参数类型的影响,假设您将16383个字符串发送到函数中,每个字符串的大小约为2MB,程序是否仍会运行测试机器上的异常?? 我看到了@rmiesen上传的代码,它充满了int参数. (2认同)

Mik*_*ski 55

这是你的理论答案:

为了将方法参数压入堆栈,已编译的代码具有以下MSIL操作码可供选择:

ldarg.0

ldarg.1

ldarg.2

ldarg.3

ldarg.S

ldarg

ldarg.0to ldarg.3用于将前4个方法参数压入堆栈(包括this作为实例方法的第一个参数).

ldarg.S 采用8位参数编号,因此它可用于将最多256个参数压入堆栈.

这让我们ldarg看起来很旧,它可以处理大多数方法参数:它采用无符号的16位参数编号.因此可以成功编译成有效MSIL的最大数量的参数是2^16 = 65,536.

然而,正如其他人所指出的那样,在实际尝试根据系统的平台/体系结构执行方法时,存在各种实际的堆栈大小限制.根据rmiesen的回答,看起来当前的.NET实现限制了运行时堆栈的最大大小2^14.

  • CIL还将参数数组的长度存储在无符号短路中,因此长度不能超过65,535. (3认同)