Параметры string.Format()

Сколько параметров вы можете передать в метод string.Format()?

На нем должен быть какой-то теоретический или принудительный предел. Это зависит от ограничений типа params [] или использования памяти приложения, которое его использует или что-то еще?

Ответы

Ответ 1

ОК, я выхожу из укрытия... Я использовал следующую программу, чтобы проверить, что происходит, и в то время как Марк указал, что строка, подобная этой "{0} {1} {2}... {2147483647} преуспел бы предел памяти 2 GiB перед списком аргументов, мои выводы не соответствовали вашим. Таким образом, жесткий предел количества параметров, которые вы можете поместить в строку. Метод вызова метода должен быть 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();

Любите людей обсуждения!

Ответ 2

Не знаю, насколько я знаю...

Ну, теоретический предел был бы предел int32 для массива, но вы дошли до предела длины строки задолго до этого, я думаю...

Просто не сходите с ума; -p Может быть, лучше написать много мелких фрагментов (например) файла или ответа, чем один огромный удар.

edit - он выглядел, как будто в IL (0xf4240) был предел, но, видимо, это не совсем так, как кажется; Я могу сделать его достаточно большим (2 ^ 24), прежде чем я просто исчерпаю системную память...


Обновление; мне кажется, что ограничивающая точка - это строка формата... те {1000001} {1000002} складываются... быстрый бит математики (ниже) показывает, что максимальное полезное количество аргументов мы можем использовать 206,449,129:

    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);

Ответ 3

Развернувшись на подробном ответе Марка.

Единственное другое ограничение, которое важно для отладчика. Когда вы передаете определенное количество параметров непосредственно функции, отладчик становится менее функциональным в этом методе. Я считаю, что предел составляет 64 параметра.

Примечание. Это не означает массив с 64 членами, но 64 параметра передаются непосредственно функции.

Вы можете смеяться и говорить "кто это сделает?" что, безусловно, является правильным вопросом. Однако LINQ делает это намного проще, чем вы думаете. Под капотом в LINQ компилятор генерирует много кода. Возможно, что для большого генерирующего SQL-запроса, где выбрано более 64 полей, вы попали бы в эту проблему. Поскольку компилятор под капотом должен будет передать все поля конструктору анонимного типа.

Еще один угловой случай.

Ответ 4

Учитывая, что как предел класса Array, так и класс String являются верхним пределом Int32 (здесь зарегистрировано в 2 147 483 647: Int32 Structure), разумно полагать, что это значение является предел числовой строки параметров формата.

Обновление. Проверяя отражатель, Джон прав. String.Format, используя рефлектор Red Gate, показывает 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) достаточно, чтобы убить большую часть этого числа. Ergo, '2,147,483,647 = x + 8x' оставляет нас с x = 238 609,294 (теоретический).

Это гораздо меньше, чем это, конечно; поскольку ребята в комментариях упомянули, что строка, поражающая ограничение длины строки раньше, весьма вероятна.

Возможно, кому-то нужно просто закодировать это в проблему с машиной!: P