C# string.Format()参数

C# string.Format()参数,c#,language-features,C#,Language Features,一个string.Format()方法可以传递多少个参数 一定有某种理论上的或强制的限制。它是基于params[]类型的限制,还是使用它的应用程序的内存使用量,还是完全基于其他原因?据我所知不是这样 理论上的限制是数组的int32限制,但在那之前很久你就已经达到了字符串长度限制,我想 只是不要为此发疯-p在一个文件或响应中写入大量的小片段(例如)可能比一次巨大的点击要好 编辑-看起来好像IL(0xf4240)中有一个限制,但显然这与它看起来的不完全一样;在系统内存耗尽之前,我可以让它变得相当大(

一个string.Format()方法可以传递多少个参数


一定有某种理论上的或强制的限制。它是基于params[]类型的限制,还是使用它的应用程序的内存使用量,还是完全基于其他原因?

据我所知不是这样

理论上的限制是数组的int32限制,但在那之前很久你就已经达到了字符串长度限制,我想

只是不要为此发疯-p在一个文件或响应中写入大量的小片段(例如)可能比一次巨大的点击要好

编辑-看起来好像IL(0xf4240)中有一个限制,但显然这与它看起来的不完全一样;在系统内存耗尽之前,我可以让它变得相当大(2^24)


更新;在我看来,边界点是格式字符串。。。那些{1000001}{1000002}加起来。。。简单的数学计算(如下)表明,我们可以使用的最大有用的参数数是206449129:

    long remaining = 2147483647;// max theoretical format arg length
    long count = 10; // i.e. {0}-{9}
    long len = 1;
    int total = 0;
    while (remaining >= 0) {
        for(int i = 0 ; i < count && remaining >= 0; i++) {
            total++;
            remaining -= len + 2; // allow for {}
        }
        count *= 10;
        len++;
    }

    Console.WriteLine(total - 1);
long剩余=2147483647;//最大理论格式参数长度
长计数=10;//i、 e.{0}-{9}
长透镜=1;
int-total=0;
而(剩余>=0){
对于(int i=0;i=0;i++){
总计++;
剩余-=len+2;//允许{}
}
计数*=10;
len++;
}
控制台写入线(总计-1);

考虑到数组类和字符串类的限制都是Int32的上限(此处记录为2147483647:),有理由相信该值是格式参数字符串数量的限制

更新检查反射器后,John是对的。格式,使用红色门反射器,显示ff:

public static string Format(IFormatProvider provider, string format, params object[] args)
{
    if ((format == null) || (args == null))
    {
        throw new ArgumentNullException((format == null) ? "format" : "args");
    }
    StringBuilder builder = new StringBuilder(format.Length + (args.Length * 8));
    builder.AppendFormat(provider, format, args);
    return builder.ToString();
}
format.Length+(args.Length*8)
代码的一部分足以杀死大部分这一数字。因此,“2147483647=x+8x”留给我们的是x=238609294(理论值)

当然远低于这个数字;正如评论中提到的,前面的字符串很可能达到字符串长度限制


也许有人应该把它编码成一个机器问题P

扩展Marc的详细答案

唯一重要的其他限制是调试器。一旦您将一定数量的参数直接传递给函数,调试器在该方法中的功能就会减弱。我认为限制是64个参数

注意:这并不意味着有64个成员的数组,而是直接传递给函数的64个参数

你可能会笑着说“谁会这么做?”这当然是一个正确的问题。然而LINQ让这比你想象的要容易得多。在LINQ中,编译器会生成大量代码。对于选择了64个以上字段的大型generate SQL查询,您可能会遇到此问题。因为后台编译器需要将所有字段传递给匿名类型的构造函数


这仍然是一个棘手的问题

好吧,我从躲藏中走出来。。。我使用下面的程序来验证发生了什么,虽然Marc指出像这样的字符串“{0}{1}{2}…{2147483647}”将在参数列表之前超过2 GiB的内存限制,但我的发现与您的不匹配。因此,可以在string.Format方法调用中输入的参数数量的硬限制必须是107713904

int i = 0;
long sum = 0;
while (sum < int.MaxValue)
{
    var s = sizeof(char) * ("{" + i + "}").Length;
    sum += s; // pseudo append
    ++i;
}
Console.WriteLine(i);
Console.ReadLine();
inti=0;
长和=0;
while(总和

爱讨论的人

哇,一个任意的无文件限制。。。我不喜欢那样+1用于研究。CLR不支持大于2GiB的对象。因为format方法为每个参数预先分配了一个StringBuilder,每个参数有8个字符,所以一个理论极限是int.MaxValue/(sizeof(char)*8),它等于134217728。没关系,我将它作为John的答案发布。开玩笑!我只是开玩笑:)+1个很好的答案Marc@John-你确定8个字符的细节吗?只有一个StringBuilder,不管参数的数量如何……是的!转到string.Format(IFormatProvider,string Format,params object[]args)它尝试分配这个新的StringBuilder(Format.Length+(args.Length*8));这最终会调用FastAllocateString(int-capacity),我只能假设它会为每个字符分配2个字节此外,在这两种情况下,格式字符串对您的影响更大。。。。{1000000}{1000001}{1000002}等。。。它加起来很快…@Marc-是的,格式字符串本身应该更快达到2 GiB的限制…@Jon Limjap-嗯,这有点多余,我喜欢注释;)