Решение использовать две фигурные скобки для печати единственной фигурной скобки в строке форматирования приводит к интересному результату.
Если ограничится стандартным способом использования фигурных скобок при форматировании строк, можно написать код такого типа:
[C#]
int i = 42;
string s = String.Format("{0}", i); //prints '42'
Однако, что если следует распечатать '{42}'? Довольно очевидным решением может показаться следующая строка кода, основанная на управляющих последоватедбностях для фигурных скобок:
[C#]
int i = 42;
string s = String.Format("{{{0}}}", i); //prints '{42}'
Теперь хотелось бы использовать преимущества различных вариантов форматирования и указать формат для переменной. Желательно распечатать ее в формате Number («Число»), используя определитель N:
[C#]
int i = 42;
string s = String.Format("{0:N}", i); //prints '42.00'
Двигаемся дальше. Требуется распечатать значение числа с фигурными скобками вокруг него, используя определитель формата Number. Можно ожидать, что сработает следующий прием:
[C#]
int i = 42;
string s = String.Format("{{{0:N}}}", i); //prints '{N}'
Возникает вопрос – почему сорвалась последняя попытка? Для понимания этого необходимо знать две вещи.
- При предоставлении определителя формата форматирование строки требует совершить следующие действия:
- Определить, длиннее ли определитель одного знака: если это так, следует предположить, что определитель является нестандартным форматом. Нестандартный формат будет использовать подходящие замены для вашего формата, но если неизвестно, что делать с каким-либо знаком, он просто выпишет его как литерал, найденный в формате.
- Определить, поддерживается ли определитель из одного знака (такой как 'N' для форматирования чисел). Если это так, форматировать соответствующим образом. Если нет, выдать ArgumnetException.
- При попытке установить, следует ли печатать фигурную скобку, фигурные скобки обрабатываются в порядке их получения. Таким образом, в последовательности "{{{" два первых знака будут трактоваться как управляющая последовательность и будет напечатан литерал '{', а третья фигурная скобка начнет раздел форматирования. На той же основе в строке "}}}" две первые фигурных скобки воспримутся как одна закрывающаяся скобка, следовательно, в формат строки будет вписана '}' , а последняя фигурная скобка будет рассмотрена как завершающая раздел форматирования.
Пользуясь этой информацией, можно понять, что происходит в случае "{{{0:N}}}". Первые две фигурные скобки представляют собой управляющую последовательность, после которой начинается раздел форматирования. Однако, символ закрывающейся фигурной скобки появляется перед закрытием раздела форматирования . Следовательно, в действительности отдел форматирования интерпретируется, как содержащий "0:N}".
Теперь средство форматирования просматривает определитель формата и принимает за него "N}". Следовательно, оно интерпретирует его как созданный разработчиком нестандартный формат, а поскольку ни N, ни } ничего не значат для нестандартного числового формата, выписываются просто эти символы, а не значение переменной, на которую идет ссылка.
Последний фрагмент не вполне понятен, но его можно сделать яснее, сравнив со следующим:
[C#]
int i = 42;
string s = String.Format("{0:N!}", i); //prints 'N!'
То же самое происходит и в этой ситуации, но в отсутствие управляющих последовательностей все несколько яснее. Грубо говоря, определитель формата видится как "N!", что интерпретируется как нестандартный формат (длиннее одного знака), а поскольку нестандартный формат не имеет особого отношения к цифрам, то N! просто используется как значение.
Для связи
[Mail]