Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этой статье приводятся дополнительные замечания к справочной документации по этому API.
Это важно
Вместо вызова метода String.Format или использования составных строк форматирования можно использовать интерполированные строки , если язык поддерживает их. Интерполированная строка — это строка, содержащая интерполированные выражения. Каждое интерполированное выражение вычисляется со значением выражения и вставляется в результирующую строку при присвоении строки. Дополнительные сведения см. в разделе "Интерполяция строк( справочник по C#) и интерполированные строки (справочник по Visual Basic)".
Примеры
Многочисленные примеры, вызывающие метод Format, разбросаны по всей этой статье. Вы также можете скачать полный набор примеров String.Format
, включаемых в проект .NET Core для C#.
Ниже приведены некоторые примеры, включенные в статью:
Создать строку формата
Вставка строки
Элемент формата
Форматирование элементов с одинаковым индексом
Управление форматированным выводом
Форматирование элементов управления
Интервалы управления
Выравнивание элементов управления
Управление числом целочисленных цифр
Управление числом цифр после десятичного разделителя
Включите литеральные фигурные скобки в строку результата
Сделайте строки форматирования с учётом культурных особенностей
Сделайте строки форматирования учитывающими культурные особенности
Настройка операции форматирования
Настраиваемая операция форматирования
Провайдер перехвата и форматировщик римских чисел
Начало работы с методом String.Format
Используйте, String.Format если необходимо вставить значение объекта, переменной или выражения в другую строку. Например, можно вставить значение значения Decimal в строку, чтобы отобразить ее пользователю в виде одной строки:
Decimal pricePerOunce = 17.36m;
String s = String.Format("The current price is {0} per ounce.",
pricePerOunce);
Console.WriteLine(s);
// Result: The current price is 17.36 per ounce.
let pricePerOunce = 17.36m
String.Format("The current price is {0} per ounce.", pricePerOunce)
|> printfn "%s"
// Result: The current price is 17.36 per ounce.
Dim pricePerOunce As Decimal = 17.36D
Dim s As String = String.Format("The current price is {0} per ounce.",
pricePerOunce)
' Result: The current price is 17.36 per ounce.
И вы можете управлять форматированием этого значения:
Decimal pricePerOunce = 17.36m;
String s = String.Format("The current price is {0:C2} per ounce.",
pricePerOunce);
Console.WriteLine(s);
// Result if current culture is en-US:
// The current price is $17.36 per ounce.
let pricePerOunce = 17.36m
String.Format("The current price is {0:C2} per ounce.", pricePerOunce)
|> printfn "%s"
// Result if current culture is en-US:
// The current price is $17.36 per ounce.
Dim pricePerOunce As Decimal = 17.36D
Dim s As String = String.Format("The current price is {0:C2} per ounce.",
pricePerOunce)
' Result if current culture is en-US:
' The current price is $17.36 per ounce.
Помимо форматирования, можно также управлять выравниванием и интервалом.
Вставка строки
String.Format начинается со строки форматирования, за которой следует один или несколько объектов или выражений, которые будут преобразованы в строки и вставлены в указанное место в строке форматирования. Рассмотрим пример.
decimal temp = 20.4m;
string s = String.Format("The temperature is {0}°C.", temp);
Console.WriteLine(s);
// Displays 'The temperature is 20.4°C.'
let temp = 20.4m
String.Format("The temperature is {0}°C.", temp)
|> printfn "%s"
// Displays 'The temperature is 20.4°C.'
Dim temp As Decimal = 20.4D
Dim s As String = String.Format("The temperature is {0}°C.", temp)
Console.WriteLine(s)
' Displays 'The temperature is 20.4°C.'
Строка {0}
форматирования — это элемент формата.
0
— индекс объекта, строковое значение которого будет вставлено по этой позиции. (Индексы начинаются с 0.) Если объект, который нужно вставить, не является строкой, его ToString
метод вызывается для преобразования его в один перед вставкой в результирующую строку.
Ниже приведен еще один пример, использующий два элемента форматирования и два объекта в списке объектов:
string s = String.Format("At {0}, the temperature is {1}°C.",
DateTime.Now, 20.4);
Console.WriteLine(s);
// Output similar to: 'At 4/10/2015 9:29:41 AM, the temperature is 20.4°C.'
String.Format("At {0}, the temperature is {1}°C.", DateTime.Now, 20.4)
|> printfn "%s"
// Output similar to: 'At 4/10/2015 9:29:41 AM, the temperature is 20.4°C.'
Dim s As String = String.Format("At {0}, the temperature is {1}°C.",
Date.Now, 20.4)
' Output similar to: 'At 4/10/2015 9:29:41 AM, the temperature is 20.4°C.'
У вас может быть столько элементов формата и столько объектов в списке объектов, сколько нужно, если индекс каждого элемента форматирования имеет соответствующий объект в списке объектов. Вам также не нужно беспокоиться, какую перегрузку вы вызываете, компилятор выберет подходящую для вас.
Форматирование элементов управления
Вы можете следовать индексу в элементе формата с строкой форматирования, чтобы управлять форматированием объекта. Например, {0:d}
применяет строку формата "d" к первому объекту в списке объектов. Ниже приведен пример с одним объектом и двумя элементами формата:
string s = String.Format("It is now {0:d} at {0:t}", DateTime.Now);
Console.WriteLine(s);
// Output similar to: 'It is now 4/10/2015 at 10:04 AM'
String.Format("It is now {0:d} at {0:t}", DateTime.Now)
|> printfn "%s"
// Output similar to: 'It is now 4/10/2015 at 10:04 AM'
Dim s As String = String.Format("It is now {0:d} at {0:t}",
Date.Now)
' Output similar to: 'It is now 4/10/2015 at 10:04 AM'
Многочисленные типы поддерживают строки форматирования, включая все числовые типы (как стандартные , так инастраиваемые строки форматирования), все даты и время (стандартные инастраиваемые строки форматирования) и интервалы времени (как стандартные, так инастраиваемые строки форматирования), все типы перечислений и GUID. Вы также можете добавить поддержку строк форматирования в собственные типы.
Интервалы управления
Ширину строки, вставленной в результирующую строку, можно определить с помощью синтаксиса, например {0,12}
, который вставляет 12-символьную строку. В этом случае строковое представление первого объекта выровнено вправо в поле шириной 12 символов. (Если строковое представление первого объекта имеет длину более 12 символов, тогда предпочтительная ширина поля игнорируется, и вся строка вставляется в результирующую строку.)
В следующем примере определяется 6-символьное поле для хранения строки "Год" и некоторых строк года, а также 15-символьного поля для хранения строки "Население" и некоторых данных о совокупности. Обратите внимание, что символы в этом поле выровнены по правому краю.
int[] years = { 2013, 2014, 2015 };
int[] population = { 1025632, 1105967, 1148203 };
var sb = new System.Text.StringBuilder();
sb.Append(String.Format("{0,6} {1,15}\n\n", "Year", "Population"));
for (int index = 0; index < years.Length; index++)
sb.Append(String.Format("{0,6} {1,15:N0}\n", years[index], population[index]));
Console.WriteLine(sb);
// Result:
// Year Population
//
// 2013 1,025,632
// 2014 1,105,967
// 2015 1,148,203
open System
open System.Text
let years = [| 2013; 2014; 2015 |]
let population = [| 1025632; 1105967; 1148203 |]
let sb = StringBuilder()
sb.Append(String.Format("{0,6} {1,15}\n\n", "Year", "Population")) |> ignore
for i = 0 to years.Length - 1 do
sb.Append(String.Format("{0,6} {1,15:N0}\n", years[i], population[i])) |> ignore
printfn $"{sb}"
// Result:
// Year Population
//
// 2013 1,025,632
// 2014 1,105,967
// 2015 1,148,203
Dim years() As Integer = {2013, 2014, 2015}
Dim population() As Integer = {1025632, 1105967, 1148203}
Dim sb As New StringBuilder()
sb.Append(String.Format("{0,6} {1,15}{2}{2}",
"Year", "Population", vbCrLf))
For index As Integer = 0 To years.Length - 1
sb.AppendFormat("{0,6} {1,15:N0}{2}",
years(index), population(index), vbCrLf)
Next
' Result:
' Year Population
'
' 2013 1,025,632
' 2014 1,105,967
' 2015 1,148,203
Выравнивание элементов управления
По умолчанию строки выравниваются по правому краю в своём поле, если указана ширина поля. Чтобы выровнять строки по левому краю в поле, укажите ширину поля отрицательным знаком, например {0,-12}
, для определения 12-символьного поля, выровненного по левому краю.
Следующий пример аналогичен предыдущему, но в нём выравниваются по левому краю как метки, так и данные.
int[] years = { 2013, 2014, 2015 };
int[] population = { 1025632, 1105967, 1148203 };
String s = String.Format("{0,-10} {1,-10}\n\n", "Year", "Population");
for (int index = 0; index < years.Length; index++)
s += String.Format("{0,-10} {1,-10:N0}\n",
years[index], population[index]);
Console.WriteLine($"\n{s}");
// Result:
// Year Population
//
// 2013 1,025,632
// 2014 1,105,967
// 2015 1,148,203
let years = [| 2013; 2014; 2015 |]
let population = [| 1025632; 1105967; 1148203 |]
let mutable s = String.Format("{0,-10} {1,-10}\n\n", "Year", "Population")
for i = 0 to years.Length - 1 do
s <- s + String.Format("{0,-10} {1,-10:N0}\n", years[i], population[i])
printfn $"\n{s}"
// Result:
// Year Population
//
// 2013 1,025,632
// 2014 1,105,967
// 2015 1,148,203
Dim years() As Integer = {2013, 2014, 2015}
Dim population() As Integer = {1025632, 1105967, 1148203}
Dim s As String = String.Format("{0,-10} {1,-10}{2}{2}",
"Year", "Population", vbCrLf)
For index As Integer = 0 To years.Length - 1
s += String.Format("{0,-10} {1,-10:N0}{2}",
years(index), population(index), vbCrLf)
Next
' Result:
' Year Population
'
' 2013 1,025,632
' 2014 1,105,967
' 2015 1,148,203
String.Format использует функцию составного форматирования. Дополнительные сведения см. в разделе Составное форматирование.
Какой метод я должен вызвать?
Цель | Метод вызова |
---|---|
Отформатируйте один или несколько объектов с помощью текущих культурных параметров. | За исключением перегрузок, включающих параметр provider , остальные перегрузки Format включают параметр String, за которым следует один или несколько параметров объекта. Из-за этого вам не нужно решать, какую перегрузку Format хотите вызвать. Компилятор языка выбирает соответствующую перегрузку из перегрузок, которые не имеют provider параметра, в зависимости от списка аргументов. Например, если в списке аргументов есть пять аргументов, компилятор вызывает Format(String, Object[]) метод. |
Отформатируйте один или несколько объектов, используя соглашения определенной культуры. | За каждой перегрузкой Format, начинающейся с provider параметра, следует String параметр и один или более параметров объекта. Из-за этого вам не требуется определять конкретную Format перегрузку, которую вы планируете вызвать. Компилятор языка выбирает соответствующую перегрузку из перегрузок, имеющих provider параметр, в зависимости от списка аргументов. Например, если в списке аргументов есть пять аргументов, компилятор вызывает Format(IFormatProvider, String, Object[]) метод. |
Выполните пользовательскую операцию форматирования либо с ICustomFormatter реализацией, либо IFormattable реализацией. | Любой из четырех перегрузок с параметром provider . Компилятор выбирает соответствующую перегрузку из перегрузок, имеющих provider параметр, на основе списка аргументов. |
Кратко о методе Format
Каждая перегрузка метода Format использует возможность составного форматирования для включения нулевых индексированных заполнителей, называемых элементами формата, в составную строку форматирования. Во время выполнения каждый элемент формата заменяется строковым представлением соответствующего аргумента в списке параметров. Если значение аргумента — это null
, элемент форматирования заменяется на String.Empty. Например, следующий вызов Format(String, Object, Object, Object) метода включает строку формата с тремя элементами формата, {0}{1}и {2}списком аргументов с тремя элементами.
DateTime dat = new DateTime(2012, 1, 17, 9, 30, 0);
string city = "Chicago";
int temp = -16;
string output = String.Format("At {0} in {1}, the temperature was {2} degrees.",
dat, city, temp);
Console.WriteLine(output);
// The example displays output like the following:
// At 1/17/2012 9:30:00 AM in Chicago, the temperature was -16 degrees.
open System
let dat = DateTime(2012, 1, 17, 9, 30, 0)
let city = "Chicago"
let temp = -16
String.Format("At {0} in {1}, the temperature was {2} degrees.", dat, city, temp)
|> printfn "%s"
// The example displays output like the following:
// At 1/17/2012 9:30:00 AM in Chicago, the temperature was -16 degrees.
Dim dat As Date = #1/17/2012 9:30AM#
Dim city As String = "Chicago"
Dim temp As Integer = -16
Dim output As String = String.Format("At {0} in {1}, the temperature was {2} degrees.",
dat, city, temp)
Console.WriteLine(output)
' The example displays the following output:
' At 1/17/2012 9:30:00 AM in Chicago, the temperature was -16 degrees.
Элемент формата
Элемент формата имеет следующий синтаксис:
{index[,width][:formatString]}
Квадратные скобки указывают необязательные элементы. Необходимы открывающие и закрывающие фигурные скобки. (Чтобы включить литеральное открытие или закрытие фигурной скобки в строке формата, см. раздел Экранирование фигурных скобок в статье Составное форматирование.)
Например, элемент форматирования для форматирования значения валюты может выглядеть следующим образом:
var value = String.Format("{0,-10:C}", 126347.89m);
Console.WriteLine(value);
open System
String.Format("{0,-10:C}", 126347.89m)
|> printfn "%s"
String.Format("{0,-10:C}", 126347.89D)
Элемент формата содержит следующие элементы:
index
Отсчитываемый от нуля индекс аргумента, строковое представление которого должно быть включено в эту позицию в строке. Если этот аргумент имеет значение null
, пустая строка будет включена в эту позицию в строке.
width
Необязательно. Целое число со знаком, указывающее общую длину поля, в которое вставляется аргумент, и сообщающее, выровнен ли он вправо (если целое число положительное) или влево (если целое число отрицательное). Если не указано width
, строковое представление соответствующего аргумента вставляется в поле без начальных или конечных пробелов.
Если значение width
меньше длины вставленного аргумента, игнорируется и width
длина строкового представления аргумента используется в качестве ширины поля.
formatString
Необязательно. Строка, указывающая формат строки результата соответствующего аргумента. Если не указано formatString
, вызывается метод без ToString
параметров соответствующего аргумента для создания строкового представления. При указании formatString
аргумент, на который ссылается форматный элемент, должен реализовать интерфейс IFormattable. Типы, поддерживающие строки формата, включают:
Все целочисленные и с плавающей запятой типы. (См. стандартные числовые строки и настраиваемые строки числовых форматов.)
DateTime и DateTimeOffset. (См. стандартные строки формата даты и времени и настраиваемые строки формата даты и времени.)
Все типы перечисления. (См. формат строк перечисления.)
TimeSpan значения. (См. стандартные форматные строки TimeSpan и настраиваемые форматные строки TimeSpan.)
Идентификаторы GUID. (См. Guid.ToString(String) метод.)
Однако любой пользовательский тип может реализовать IFormattable или расширить реализацию существующего типа IFormattable.
В следующем примере используются аргументы width
и formatString
для создания форматированных выходных данных.
// Create array of 5-tuples with population data for three U.S. cities, 1940-1950.
Tuple<string, DateTime, int, DateTime, int>[] cities =
{ Tuple.Create("Los Angeles", new DateTime(1940, 1, 1), 1504277,
new DateTime(1950, 1, 1), 1970358),
Tuple.Create("New York", new DateTime(1940, 1, 1), 7454995,
new DateTime(1950, 1, 1), 7891957),
Tuple.Create("Chicago", new DateTime(1940, 1, 1), 3396808,
new DateTime(1950, 1, 1), 3620962),
Tuple.Create("Detroit", new DateTime(1940, 1, 1), 1623452,
new DateTime(1950, 1, 1), 1849568) };
// Display header
var header = String.Format("{0,-12}{1,8}{2,12}{1,8}{2,12}{3,14}\n",
"City", "Year", "Population", "Change (%)");
Console.WriteLine(header);
foreach (var city in cities) {
var output = String.Format("{0,-12}{1,8:yyyy}{2,12:N0}{3,8:yyyy}{4,12:N0}{5,14:P1}",
city.Item1, city.Item2, city.Item3, city.Item4, city.Item5,
(city.Item5 - city.Item3)/ (double)city.Item3);
Console.WriteLine(output);
}
// The example displays the following output:
// City Year Population Year Population Change (%)
//
// Los Angeles 1940 1,504,277 1950 1,970,358 31.0 %
// New York 1940 7,454,995 1950 7,891,957 5.9 %
// Chicago 1940 3,396,808 1950 3,620,962 6.6 %
// Detroit 1940 1,623,452 1950 1,849,568 13.9 %
// Create a list of 5-tuples with population data for three U.S. cities, 1940-1950.
let cities =
[ "Los Angeles", DateTime(1940, 1, 1), 1504277, DateTime(1950, 1, 1), 1970358
"New York", DateTime(1940, 1, 1), 7454995, DateTime(1950, 1, 1), 7891957
"Chicago", DateTime(1940, 1, 1), 3396808, DateTime(1950, 1, 1), 3620962
"Detroit", DateTime(1940, 1, 1), 1623452, DateTime(1950, 1, 1), 1849568 ]
// Display header
String.Format("{0,-12}{1,8}{2,12}{1,8}{2,12}{3,14}\n", "City", "Year", "Population", "Change (%)")
|> printfn "%s"
for name, year1, pop1, year2, pop2 in cities do
String.Format("{0,-12}{1,8:yyyy}{2,12:N0}{3,8:yyyy}{4,12:N0}{5,14:P1}",
name, year1, pop1, year2, pop2,
double (pop2 - pop1) / double pop1)
|> printfn "%s"
// The example displays the following output:
// City Year Population Year Population Change (%)
//
// Los Angeles 1940 1,504,277 1950 1,970,358 31.0 %
// New York 1940 7,454,995 1950 7,891,957 5.9 %
// Chicago 1940 3,396,808 1950 3,620,962 6.6 %
// Detroit 1940 1,623,452 1950 1,849,568 13.9 %
Module Example3
Public Sub Main()
' Create array of 5-tuples with population data for three U.S. cities, 1940-1950.
Dim cities() =
{Tuple.Create("Los Angeles", #1/1/1940#, 1504277, #1/1/1950#, 1970358),
Tuple.Create("New York", #1/1/1940#, 7454995, #1/1/1950#, 7891957),
Tuple.Create("Chicago", #1/1/1940#, 3396808, #1/1/1950#, 3620962),
Tuple.Create("Detroit", #1/1/1940#, 1623452, #1/1/1950#, 1849568)}
' Display header
Dim header As String = String.Format("{0,-12}{1,8}{2,12}{1,8}{2,12}{3,14}",
"City", "Year", "Population", "Change (%)")
Console.WriteLine(header)
Console.WriteLine()
For Each city In cities
Dim output = String.Format("{0,-12}{1,8:yyyy}{2,12:N0}{3,8:yyyy}{4,12:N0}{5,14:P1}",
city.Item1, city.Item2, city.Item3, city.Item4, city.Item5,
(city.Item5 - city.Item3) / city.Item3)
Console.WriteLine(output)
Next
End Sub
End Module
' The example displays the following output:
' City Year Population Year Population Change (%)
'
' Los Angeles 1940 1,504,277 1950 1,970,358 31.0 %
' New York 1940 7,454,995 1950 7,891,957 5.9 %
' Chicago 1940 3,396,808 1950 3,620,962 6.6 %
' Detroit 1940 1,623,452 1950 1,849,568 13.9 %
Форматирование аргументов
Элементы форматирования обрабатываются последовательно с начала строки. Каждый элемент формата имеет индекс, соответствующий объекту в списке аргументов метода. Метод Format извлекает аргумент и получает строковое представление следующим образом:
Если аргумент
null
, метод вставляет String.Empty в строку результата. Вам не нужно беспокоиться об обработке NullReferenceException, связанной с пустыми аргументами.При вызове перегрузки Format(IFormatProvider, String, Object[]), если реализация объекта
provider
в IFormatProvider.GetFormat возвращает реализацию ICustomFormatter, которая не равна NULL, аргумент передается в его метод ICustomFormatter.Format(String, Object, IFormatProvider). Если элемент формата содержитformatString
аргумент, он передается в качестве первого аргумента методу. ICustomFormatter Если реализация доступна и создает непустую строку, эта строка возвращается в виде строкового представления аргумента; в противном случае выполняется следующий шаг.Если аргумент реализует IFormattable интерфейс, его IFormattable.ToString реализация вызывается.
Метод аргумента без
ToString
параметров, который либо переопределяет, либо наследует реализацию базового класса, вызывается.
Для примера перехвата вызовов метода ICustomFormatter.Format, который позволяет увидеть, какую информацию метод Format передает методу форматирования для каждого элемента в строке составного формата, см. Пример: провайдер перехвата и форматировщик римских чисел.
Дополнительные сведения см. в разделе "Порядок обработки".
Форматирование элементов с одинаковым индексом
Метод Format создает FormatException исключение, если индекс элемента индекса больше или равен числу аргументов в списке аргументов.
format
Однако может содержать больше элементов формата, чем аргументы, если несколько элементов формата имеют один и тот же индекс. В вызове Format(String, Object) метода в следующем примере список аргументов имеет один аргумент, но строка формата включает два элемента формата: один отображает десятичное значение числа, а другой — шестнадцатеричное значение.
short[] values= { Int16.MinValue, -27, 0, 1042, Int16.MaxValue };
Console.WriteLine("{0,10} {1,10}\n", "Decimal", "Hex");
foreach (short value in values)
{
string formatString = String.Format("{0,10:G}: {0,10:X}", value);
Console.WriteLine(formatString);
}
// The example displays the following output:
// Decimal Hex
//
// -32768: 8000
// -27: FFE5
// 0: 0
// 1042: 412
// 32767: 7FFF
open System
let values= [| Int16.MinValue; -27s; 0s; 1042s; Int16.MaxValue |]
printfn "%10s %10s\n" "Decimal" "Hex"
for value in values do
String.Format("{0,10:G}: {0,10:X}", value)
|> printfn "%s"
// The example displays the following output:
// Decimal Hex
//
// -32768: 8000
// -27: FFE5
// 0: 0
// 1042: 412
// 32767: 7FFF
Module Example1
Public Sub Main()
Dim values() As Short = {Int16.MinValue, -27, 0, 1042, Int16.MaxValue}
Console.WriteLine("{0,10} {1,10}", "Decimal", "Hex")
Console.WriteLine()
For Each value As Short In values
Dim formatString As String = String.Format("{0,10:G}: {0,10:X}", value)
Console.WriteLine(formatString)
Next
End Sub
End Module
' The example displays the following output:
' Decimal Hex
'
' -32768: 8000
' -27: FFE5
' 0: 0
' 1042: 412
' 32767: 7FFF
Формат и культура
Как правило, объекты в списке аргументов преобразуются в их строковые представления согласно культурным соглашениям текущего языка и региональных настроек, возвращаемых свойством CultureInfo.CurrentCulture. Это поведение можно контролировать, вызвав одну из перегрузок Format, включающую параметр provider
. Параметр provider
— это механизм, который предоставляет пользовательские IFormatProvider и культурно-специфические параметры форматирования, используемые для управления процессом форматирования.
Интерфейс IFormatProvider имеет один член, который отвечает за возврат объекта, GetFormatпредоставляющего сведения о форматировании. .NET имеет три IFormatProvider реализации, которые обеспечивают форматирование, зависящее от культуры:
- CultureInfo. Его GetFormat метод возвращает объект, зависящий от культуры, для форматирования числовых значений и объект, зависящий от культуры, для форматирования значений даты и времени.
- DateTimeFormatInfo, который используется для форматирования значений даты и времени с учётом культурных особенностей. Его GetFormat метод возвращает себя.
- NumberFormatInfo, который используется для форматирования числовых значений в зависимости от культурных особенностей. Его GetFormat(Type) метод возвращает себя.
Пользовательские операции форматирования
Можно также вызвать любые специальные перегрузки метода Format, которые содержат параметр provider
типа IFormatProvider, чтобы осуществлять пользовательские операции форматирования. Например, можно отформатировать целое число как идентификационный номер или номер телефона. Для выполнения настраиваемого форматирования аргумент provider
должен реализовывать и интерфейс IFormatProvider, и интерфейс ICustomFormatter.
Format Когда метод передает реализацию ICustomFormatter в качестве provider
аргумента, Format метод вызывает свою IFormatProvider.GetFormat реализацию и запрашивает объект типаICustomFormatter. Затем он вызывает метод возвращаемого ICustomFormatter объекта Format для форматирования каждого элемента формата в составной строке, переданной ему.
Дополнительные сведения о предоставлении пользовательских решений форматирования см. в разделе "Практическое руководство. Определение и использование пользовательских поставщиков числовых форматов" иICustomFormatter. Пример преобразования целых чисел в форматированные пользовательские числа см. в примере: операция пользовательского форматирования. Пример преобразования байтов без знака в римские цифры см. в Пример: Поставщик перехвата и формататор римских цифр.
Пример: настраиваемая операция форматирования
В этом примере определяется поставщик формата, который форматирует целочисленное значение в виде номера учетной записи клиента в форме x-xxxxx-xx.
using System;
public class TestFormatter
{
public static void Main()
{
int acctNumber = 79203159;
Console.WriteLine(String.Format(new CustomerFormatter(), "{0}", acctNumber));
Console.WriteLine(String.Format(new CustomerFormatter(), "{0:G}", acctNumber));
Console.WriteLine(String.Format(new CustomerFormatter(), "{0:S}", acctNumber));
Console.WriteLine(String.Format(new CustomerFormatter(), "{0:P}", acctNumber));
try {
Console.WriteLine(String.Format(new CustomerFormatter(), "{0:X}", acctNumber));
}
catch (FormatException e) {
Console.WriteLine(e.Message);
}
}
}
public class CustomerFormatter : IFormatProvider, ICustomFormatter
{
public object GetFormat(Type formatType)
{
if (formatType == typeof(ICustomFormatter))
return this;
else
return null;
}
public string Format(string format,
object arg,
IFormatProvider formatProvider)
{
if (! this.Equals(formatProvider))
{
return null;
}
else
{
if (String.IsNullOrEmpty(format))
format = "G";
string customerString = arg.ToString();
if (customerString.Length < 8)
customerString = customerString.PadLeft(8, '0');
format = format.ToUpper();
switch (format)
{
case "G":
return customerString.Substring(0, 1) + "-" +
customerString.Substring(1, 5) + "-" +
customerString.Substring(6);
case "S":
return customerString.Substring(0, 1) + "/" +
customerString.Substring(1, 5) + "/" +
customerString.Substring(6);
case "P":
return customerString.Substring(0, 1) + "." +
customerString.Substring(1, 5) + "." +
customerString.Substring(6);
default:
throw new FormatException(
String.Format("The '{0}' format specifier is not supported.", format));
}
}
}
}
// The example displays the following output:
// 7-92031-59
// 7-92031-59
// 7/92031/59
// 7.92031.59
// The 'X' format specifier is not supported.
open System
type CustomerFormatter() =
interface IFormatProvider with
member this.GetFormat(formatType) =
if formatType = typeof<ICustomFormatter> then
this
else
null
interface ICustomFormatter with
member this.Format(format, arg, formatProvider: IFormatProvider) =
if this.Equals formatProvider |> not then
null
else
let format =
if String.IsNullOrEmpty format then "G"
else format.ToUpper()
let customerString =
let s = string arg
if s.Length < 8 then
s.PadLeft(8, '0')
else s
match format with
| "G" ->
customerString.Substring(0, 1) + "-" +
customerString.Substring(1, 5) + "-" +
customerString.Substring 6
| "S" ->
customerString.Substring(0, 1) + "/" +
customerString.Substring(1, 5) + "/" +
customerString.Substring 6
| "P" ->
customerString.Substring(0, 1) + "." +
customerString.Substring(1, 5) + "." +
customerString.Substring 6
| _ ->
raise (FormatException $"The '{format}' format specifier is not supported.")
let acctNumber = 79203159
String.Format(CustomerFormatter(), "{0}", acctNumber)
|> printfn "%s"
String.Format(CustomerFormatter(), "{0:G}", acctNumber)
|> printfn "%s"
String.Format(CustomerFormatter(), "{0:S}", acctNumber)
|> printfn "%s"
String.Format(CustomerFormatter(), "{0:P}", acctNumber)
|> printfn "%s"
try
String.Format(CustomerFormatter(), "{0:X}", acctNumber)
|> printfn "%s"
with :? FormatException as e ->
printfn $"{e.Message}"
// The example displays the following output:
// 7-92031-59
// 7-92031-59
// 7/92031/59
// 7.92031.59
// The 'X' format specifier is not supported.
Module TestFormatter
Public Sub Main()
Dim acctNumber As Integer = 79203159
Console.WriteLine(String.Format(New CustomerFormatter, "{0}", acctNumber))
Console.WriteLine(String.Format(New CustomerFormatter, "{0:G}", acctNumber))
Console.WriteLine(String.Format(New CustomerFormatter, "{0:S}", acctNumber))
Console.WriteLine(String.Format(New CustomerFormatter, "{0:P}", acctNumber))
Try
Console.WriteLine(String.Format(New CustomerFormatter, "{0:X}", acctNumber))
Catch e As FormatException
Console.WriteLine(e.Message)
End Try
End Sub
End Module
Public Class CustomerFormatter : Implements IFormatProvider, ICustomFormatter
Public Function GetFormat(type As Type) As Object _
Implements IFormatProvider.GetFormat
If type Is GetType(ICustomFormatter) Then
Return Me
Else
Return Nothing
End If
End Function
Public Function Format(fmt As String, _
arg As Object, _
formatProvider As IFormatProvider) As String _
Implements ICustomFormatter.Format
If Not Me.Equals(formatProvider) Then
Return Nothing
Else
If String.IsNullOrEmpty(fmt) Then fmt = "G"
Dim customerString As String = arg.ToString()
if customerString.Length < 8 Then _
customerString = customerString.PadLeft(8, "0"c)
Select Case fmt
Case "G"
Return customerString.Substring(0, 1) & "-" & _
customerString.Substring(1, 5) & "-" & _
customerString.Substring(6)
Case "S"
Return customerString.Substring(0, 1) & "/" & _
customerString.Substring(1, 5) & "/" & _
customerString.Substring(6)
Case "P"
Return customerString.Substring(0, 1) & "." & _
customerString.Substring(1, 5) & "." & _
customerString.Substring(6)
Case Else
Throw New FormatException( _
String.Format("The '{0}' format specifier is not supported.", fmt))
End Select
End If
End Function
End Class
' The example displays the following output:
' 7-92031-59
' 7-92031-59
' 7/92031/59
' 7.92031.59
' The 'X' format specifier is not supported.
Пример: перехватчик и форматировщик римских чисел
В этом примере определяется настраиваемый поставщик формата, реализующий ICustomFormatter и IFormatProvider интерфейсы для выполнения двух действий:
- В нем отображаются параметры, переданные в реализацию ICustomFormatter.Format . Это позволяет узнать, какие параметры Format(IFormatProvider, String, Object[]) метод передает в пользовательскую реализацию форматирования для каждого объекта, который он пытается отформатировать. Это может быть полезно при отладке приложения.
- Если объект, который должен быть отформатирован, является значением без знака байтов, которое должно быть отформатировано с помощью стандартной строки формата R, настраиваемое средство форматирования форматирует числовое значение как римское число.
using System;
using System.Globalization;
public class InterceptProvider : IFormatProvider, ICustomFormatter
{
public object GetFormat(Type formatType)
{
if (formatType == typeof(ICustomFormatter))
return this;
else
return null;
}
public string Format(String format, Object obj, IFormatProvider provider)
{
// Display information about method call.
string formatString = format ?? "<null>";
Console.WriteLine("Provider: {0}, Object: {1}, Format String: {2}",
provider.GetType().Name, obj ?? "<null>", formatString);
if (obj == null) return String.Empty;
// If this is a byte and the "R" format string, format it with Roman numerals.
if (obj is Byte && formatString.ToUpper().Equals("R")) {
Byte value = (Byte) obj;
int remainder;
int result;
String returnString = String.Empty;
// Get the hundreds digit(s)
result = Math.DivRem(value, 100, out remainder);
if (result > 0)
returnString = new String('C', result);
value = (Byte) remainder;
// Get the 50s digit
result = Math.DivRem(value, 50, out remainder);
if (result == 1)
returnString += "L";
value = (Byte) remainder;
// Get the tens digit.
result = Math.DivRem(value, 10, out remainder);
if (result > 0)
returnString += new String('X', result);
value = (Byte) remainder;
// Get the fives digit.
result = Math.DivRem(value, 5, out remainder);
if (result > 0)
returnString += "V";
value = (Byte) remainder;
// Add the ones digit.
if (remainder > 0)
returnString += new String('I', remainder);
// Check whether we have too many X characters.
int pos = returnString.IndexOf("XXXX");
if (pos >= 0) {
int xPos = returnString.IndexOf("L");
if (xPos >= 0 & xPos == pos - 1)
returnString = returnString.Replace("LXXXX", "XC");
else
returnString = returnString.Replace("XXXX", "XL");
}
// Check whether we have too many I characters
pos = returnString.IndexOf("IIII");
if (pos >= 0)
if (returnString.IndexOf("V") >= 0)
returnString = returnString.Replace("VIIII", "IX");
else
returnString = returnString.Replace("IIII", "IV");
return returnString;
}
// Use default for all other formatting.
if (obj is IFormattable)
return ((IFormattable) obj).ToString(format, CultureInfo.CurrentCulture);
else
return obj.ToString();
}
}
public class Example
{
public static void Main()
{
int n = 10;
double value = 16.935;
DateTime day = DateTime.Now;
InterceptProvider provider = new InterceptProvider();
Console.WriteLine(String.Format(provider, "{0:N0}: {1:C2} on {2:d}\n", n, value, day));
Console.WriteLine(String.Format(provider, "{0}: {1:F}\n", "Today: ",
(DayOfWeek) DateTime.Now.DayOfWeek));
Console.WriteLine(String.Format(provider, "{0:X}, {1}, {2}\n",
(Byte) 2, (Byte) 12, (Byte) 199));
Console.WriteLine(String.Format(provider, "{0:R}, {1:R}, {2:R}\n",
(Byte) 2, (Byte) 12, (Byte) 199));
}
}
// The example displays the following output:
// Provider: InterceptProvider, Object: 10, Format String: N0
// Provider: InterceptProvider, Object: 16.935, Format String: C2
// Provider: InterceptProvider, Object: 1/31/2013 6:10:28 PM, Format String: d
// 10: $16.94 on 1/31/2013
//
// Provider: InterceptProvider, Object: Today: , Format String: <null>
// Provider: InterceptProvider, Object: Thursday, Format String: F
// Today: : Thursday
//
// Provider: InterceptProvider, Object: 2, Format String: X
// Provider: InterceptProvider, Object: 12, Format String: <null>
// Provider: InterceptProvider, Object: 199, Format String: <null>
// 2, 12, 199
//
// Provider: InterceptProvider, Object: 2, Format String: R
// Provider: InterceptProvider, Object: 12, Format String: R
// Provider: InterceptProvider, Object: 199, Format String: R
// II, XII, CXCIX
open System
open System.Globalization
type InterceptProvider() =
interface IFormatProvider with
member this.GetFormat(formatType) =
if formatType = typeof<ICustomFormatter> then
this
else
null
interface ICustomFormatter with
member _.Format(format, obj, provider: IFormatProvider) =
// Display information about method call.
let formatString =
if format = null then "<null>" else format
printfn $"Provider: {provider.GetType().Name}, Object: %A{obj}, Format String: %s{formatString}"
if obj = null then
String.Empty
else
// If this is a byte and the "R" format string, format it with Roman numerals.
match obj with
| :? byte as value when formatString.ToUpper().Equals "R" ->
let mutable returnString = String.Empty
// Get the hundreds digit(s)
let struct (result, remainder) = Math.DivRem(value, 100uy)
if result > 0uy then
returnString <- String('C', int result)
let value = byte remainder
// Get the 50s digit
let struct (result, remainder) = Math.DivRem(value, 50uy)
if result = 1uy then
returnString <- returnString + "L"
let value = byte remainder
// Get the tens digit.
let struct (result, remainder) = Math.DivRem(value, 10uy)
if result > 0uy then
returnString <- returnString + String('X', int result)
let value = byte remainder
// Get the fives digit.
let struct (result, remainder) = Math.DivRem(value, 5uy)
if result > 0uy then
returnString <- returnString + "V"
let value = byte remainder
// Add the ones digit.
if remainder > 0uy then
returnString <- returnString + String('I', int remainder)
// Check whether we have too many X characters.
let pos = returnString.IndexOf "XXXX"
if pos >= 0 then
let xPos = returnString.IndexOf "L"
returnString <-
if xPos >= 0 && xPos = pos - 1 then
returnString.Replace("LXXXX", "XC")
else
returnString.Replace("XXXX", "XL")
// Check whether we have too many I characters
let pos = returnString.IndexOf "IIII"
if pos >= 0 then
returnString <-
if returnString.IndexOf "V" >= 0 then
returnString.Replace("VIIII", "IX")
else
returnString.Replace("IIII", "IV")
returnString
// Use default for all other formatting.
| :? IFormattable as x ->
x.ToString(format, CultureInfo.CurrentCulture)
| _ ->
string obj
let n = 10
let value = 16.935
let day = DateTime.Now
let provider = InterceptProvider()
String.Format(provider, "{0:N0}: {1:C2} on {2:d}\n", n, value, day)
|> printfn "%s"
String.Format(provider, "{0}: {1:F}\n", "Today: ", DateTime.Now.DayOfWeek)
|> printfn "%s"
String.Format(provider, "{0:X}, {1}, {2}\n", 2uy, 12uy, 199uy)
|> printfn "%s"
String.Format(provider, "{0:R}, {1:R}, {2:R}\n", 2uy, 12uy, 199uy)
|> printfn "%s"
// The example displays the following output:
// Provider: InterceptProvider, Object: 10, Format String: N0
// Provider: InterceptProvider, Object: 16.935, Format String: C2
// Provider: InterceptProvider, Object: 1/31/2013 6:10:28 PM, Format String: d
// 10: $16.94 on 1/31/2013
//
// Provider: InterceptProvider, Object: Today: , Format String: <null>
// Provider: InterceptProvider, Object: Thursday, Format String: F
// Today: : Thursday
//
// Provider: InterceptProvider, Object: 2, Format String: X
// Provider: InterceptProvider, Object: 12, Format String: <null>
// Provider: InterceptProvider, Object: 199, Format String: <null>
// 2, 12, 199
//
// Provider: InterceptProvider, Object: 2, Format String: R
// Provider: InterceptProvider, Object: 12, Format String: R
// Provider: InterceptProvider, Object: 199, Format String: R
// II, XII, CXCIX
Imports System.Globalization
Public Class InterceptProvider : Implements IFormatProvider, ICustomFormatter
Public Function GetFormat(formatType As Type) As Object _
Implements IFormatProvider.GetFormat
If formatType Is GetType(ICustomFormatter) Then
Return Me
Else
Return Nothing
End If
End Function
Public Function Format(fmt As String, obj As Object, provider As IFormatProvider) As String _
Implements ICustomFormatter.Format
Dim formatString As String = If(fmt IsNot Nothing, fmt, "<null>")
Console.WriteLine("Provider: {0}, Object: {1}, Format String: {2}",
provider, If(obj IsNot Nothing, obj, "<null>"), formatString)
If obj Is Nothing Then Return String.Empty
' If this is a byte and the "R" format string, format it with Roman numerals.
If TypeOf(obj) Is Byte AndAlso formatString.ToUpper.Equals("R") Then
Dim value As Byte = CByte(obj)
Dim remainder As Integer
Dim result As Integer
Dim returnString As String = String.Empty
' Get the hundreds digit(s)
result = Math.DivRem(value, 100, remainder)
If result > 0 Then returnString = New String("C"c, result)
value = CByte(remainder)
' Get the 50s digit
result = Math.DivRem(value, 50, remainder)
If result = 1 Then returnString += "L"
value = CByte(remainder)
' Get the tens digit.
result = Math.DivRem(value, 10, remainder)
If result > 0 Then returnString += New String("X"c, result)
value = CByte(remainder)
' Get the fives digit.
result = Math.DivRem(value, 5, remainder)
If result > 0 Then returnString += "V"
value = CByte(remainder)
' Add the ones digit.
If remainder > 0 Then returnString += New String("I"c, remainder)
' Check whether we have too many X characters.
Dim pos As Integer = returnString.IndexOf("XXXX")
If pos >= 0 Then
Dim xPos As Integer = returnString.IndexOf("L")
If xPos >= 0 And xPos = pos - 1 Then
returnString = returnString.Replace("LXXXX", "XC")
Else
returnString = returnString.Replace("XXXX", "XL")
End If
End If
' Check whether we have too many I characters
pos = returnString.IndexOf("IIII")
If pos >= 0 Then
If returnString.IndexOf("V") >= 0 Then
returnString = returnString.Replace("VIIII", "IX")
Else
returnString = returnString.Replace("IIII", "IV")
End If
End If
Return returnString
End If
' Use default for all other formatting.
If obj Is GetType(IFormattable)
Return CType(obj, IFormattable).ToString(fmt, CultureInfo.CurrentCulture)
Else
Return obj.ToString()
End If
End Function
End Class
Module Example
Public Sub Main()
Dim n As Integer = 10
Dim value As Double = 16.935
Dim day As DateTime = Date.Now
Dim provider As New InterceptProvider()
Console.WriteLine(String.Format(provider, "{0:N0}: {1:C2} on {2:d}", n, value, day))
Console.WriteLine()
Console.WriteLine(String.Format(provider, "{0}: {1:F}", "Today",
CType(Date.Now.DayOfWeek, DayOfWeek)))
Console.WriteLine()
Console.WriteLine(String.Format(provider, "{0:X}, {1}, {2}\n",
CByte(2), CByte(12), CByte(199)))
Console.WriteLine()
Console.WriteLine(String.Format(provider, "{0:R}, {1:R}, {2:R}",
CByte(2), CByte(12), CByte(199)))
End Sub
End Module
' The example displays the following output:
' Provider: InterceptProvider, Object: 10, Format String: N0
' Provider: InterceptProvider, Object: 16.935, Format String: C2
' Provider: InterceptProvider, Object: 1/31/2013 6:10:28 PM, Format String: d
' 10: $16.94 on 1/31/2013
'
' Provider: InterceptProvider, Object: Today: , Format String: <null>
' Provider: InterceptProvider, Object: Thursday, Format String: F
' Today: : Thursday
'
' Provider: InterceptProvider, Object: 2, Format String: X
' Provider: InterceptProvider, Object: 12, Format String: <null>
' Provider: InterceptProvider, Object: 199, Format String: <null>
' 2, 12, 199
'
' Provider: InterceptProvider, Object: 2, Format String: R
' Provider: InterceptProvider, Object: 12, Format String: R
' Provider: InterceptProvider, Object: 199, Format String: R
' II, XII, CXCIX
Вопросы и ответы
Почему рекомендуется интерполяция строк для вызовов String.Format
метода?
Интерполяция строк:
- Более гибкий. Его можно использовать в любой строке без вызова метода, поддерживающего составное форматирование. В противном случае необходимо вызвать Format метод или другой метод, поддерживающий составное форматирование, например Console.WriteLine или StringBuilder.AppendFormat.
- Легче читаемый Поскольку выражение для вставки в строку отображается в интерполированном выражении, а не в списке аргументов, интерполированные строки проще кодировать и читать. Интерполированные строки также можно использовать в операциях объединения строк для создания более краткого, более четкого кода.
Сравнение следующих двух примеров кода иллюстрирует превосходство интерполированных строк над объединением строк и вызовами составных методов форматирования. Использование нескольких операций объединения строк в следующем примере создает подробный и сложный код.
string[] names = { "Balto", "Vanya", "Dakota", "Samuel", "Koani", "Yiska", "Yuma" };
string output = names[0] + ", " + names[1] + ", " + names[2] + ", " +
names[3] + ", " + names[4] + ", " + names[5] + ", " +
names[6];
output += "\n";
var date = DateTime.Now;
output += String.Format("It is {0:t} on {0:d}. The day of the week is {1}.",
date, date.DayOfWeek);
Console.WriteLine(output);
// The example displays the following output:
// Balto, Vanya, Dakota, Samuel, Koani, Yiska, Yuma
// It is 10:29 AM on 1/8/2018. The day of the week is Monday.
open System
let names = [| "Balto"; "Vanya"; "Dakota"; "Samuel"; "Koani"; "Yiska"; "Yuma" |]
let output =
names[0] + ", " + names[1] + ", " + names[2] + ", " +
names[3] + ", " + names[4] + ", " + names[5] + ", " +
names[6] + "\n"
let date = DateTime.Now
output + String.Format("It is {0:t} on {0:d}. The day of the week is {1}.", date, date.DayOfWeek)
|> printfn "%s"
// The example displays the following output:
// Balto, Vanya, Dakota, Samuel, Koani, Yiska, Yuma
// It is 10:29 AM on 1/8/2018. The day of the week is Monday.
Module Example12
Public Sub Main()
Dim names = {"Balto", "Vanya", "Dakota", "Samuel", "Koani", "Yiska", "Yuma"}
Dim output = names(0) + ", " + names(1) + ", " + names(2) + ", " +
names(3) + ", " + names(4) + ", " + names(5) + ", " +
names(6)
output += vbCrLf
Dim dat = DateTime.Now
output += String.Format("It is {0:t} on {0:d}. The day of the week is {1}.",
dat, dat.DayOfWeek)
Console.WriteLine(output)
End Sub
End Module
' The example displays the following output:
' Balto, Vanya, Dakota, Samuel, Koani, Yiska, Yuma
' It is 10:29 AM on 1/8/2018. The day of the week is Monday.
В отличие от этого, использование интерполированных строк в следующем примере создает гораздо более четкий, более краткий код, чем оператор объединения строк и вызов Format метода в предыдущем примере.
string[] names = { "Balto", "Vanya", "Dakota", "Samuel", "Koani", "Yiska", "Yuma" };
string output = $"{names[0]}, {names[1]}, {names[2]}, {names[3]}, {names[4]}, " +
$"{names[5]}, {names[6]}";
var date = DateTime.Now;
output += $"\nIt is {date:t} on {date:d}. The day of the week is {date.DayOfWeek}.";
Console.WriteLine(output);
// The example displays the following output:
// Balto, Vanya, Dakota, Samuel, Koani, Yiska, Yuma
// It is 10:29 AM on 1/8/2018. The day of the week is Monday.
open System
let names = [| "Balto"; "Vanya"; "Dakota"; "Samuel"; "Koani"; "Yiska"; "Yuma" |]
let output = $"{names[0]}, {names[1]}, {names[2]}, {names[3]}, {names[4]}, {names[5]}, {names[6]}"
let date = DateTime.Now
output + $"\nIt is {date:t} on {date:d}. The day of the week is {date.DayOfWeek}."
|> printfn "%s"
// The example displays the following output:
// Balto, Vanya, Dakota, Samuel, Koani, Yiska, Yuma
// It is 10:29 AM on 1/8/2018. The day of the week is Monday.
Module Example13
Public Sub Main()
Dim names = {"Balto", "Vanya", "Dakota", "Samuel", "Koani", "Yiska", "Yuma"}
Dim output = $"{names(0)}, {names(1)}, {names(2)}, {names(3)}, {names(4)}, " +
$"{names(5)}, {names(6)}"
Dim dat = DateTime.Now
output += $"{vbCrLf}It is {dat:t} on {dat:d}. The day of the week is {dat.DayOfWeek}."
Console.WriteLine(output)
End Sub
End Module
' The example displays the following output:
' Balto, Vanya, Dakota, Samuel, Koani, Yiska, Yuma
' It is 10:29 AM on 1/8/2018. The day of the week is Monday.
Где можно найти предопределенные строки формата?
- Все типы целочисленных и с плавающей запятой см. в разделе "Стандартные числовые строки" и "Настраиваемые строки числовых форматов".
- Значения даты и времени см. в разделе "Стандартные строки формата даты и времени " и "Настраиваемые строки формата даты и времени".
- Значения перечисления см. в разделе "Строки формата перечисления".
- Для значений TimeSpan см. Стандартные строки формата TimeSpan и Настраиваемые строки формата TimeSpan.
- Сведения о Guid значениях см. в разделе Guid.ToString(String) "Примечания" страницы ссылки.
Как управлять выравниванием строк результатов, заменяющих элементы формата?
Общий синтаксис элемента формата:
{index[,width][: formatString]}
width
— это целое число со знаком, определяющее ширину поля. Если это значение отрицательное, текст в текстовом поле будет выровнен по левому краю. Если условие положительное, текст выровнен по правому краю.
Как управлять числом цифр после десятичного разделителя?
Все строки стандартного числового формата, кроме "D" (который используется только с целыми числами), "G", "R" и "X", позволяют спецификатор точности, определяющий число десятичных цифр в результирующей строке. В следующем примере используются стандартные числовые строки формата для управления числом десятичных цифр в результирующем строке.
object[] values = { 1603, 1794.68235, 15436.14 };
string result;
foreach (var value in values)
{
result = String.Format("{0,12:C2} {0,12:E3} {0,12:F4} {0,12:N3} {1,12:P2}\n",
Convert.ToDouble(value), Convert.ToDouble(value) / 10000);
Console.WriteLine(result);
}
// The example displays output like the following:
// $1,603.00 1.603E+003 1603.0000 1,603.000 16.03 %
//
// $1,794.68 1.795E+003 1794.6824 1,794.682 17.95 %
//
// $15,436.14 1.544E+004 15436.1400 15,436.140 154.36 %
open System
let values: obj list = [ 1603, 1794.68235, 15436.14 ]
for value in values do
String.Format("{0,12:C2} {0,12:E3} {0,12:F4} {0,12:N3} {1,12:P2}\n", Convert.ToDouble(value), Convert.ToDouble(value) / 10000.)
|> printfn "%s"
// The example displays output like the following:
// $1,603.00 1.603E+003 1603.0000 1,603.000 16.03 %
//
// $1,794.68 1.795E+003 1794.6824 1,794.682 17.95 %
//
// $15,436.14 1.544E+004 15436.1400 15,436.140 154.36 %
Module Example7
Public Sub Main()
Dim values() As Object = {1603, 1794.68235, 15436.14}
Dim result As String
For Each value In values
result = String.Format("{0,12:C2} {0,12:E3} {0,12:F4} {0,12:N3} {1,12:P2}",
value, CDbl(value) / 10000)
Console.WriteLine(result)
Console.WriteLine()
Next
End Sub
End Module
' The example displays the following output:
' $1,603.00 1.603E+003 1603.0000 1,603.000 16.03 %
'
' $1,794.68 1.795E+003 1794.6824 1,794.682 17.95 %
'
' $15,436.14 1.544E+004 15436.1400 15,436.140 154.36 %
Если вы используете настраиваемую строку числового формата, используйте описатель формата "0", чтобы управлять числом десятичных цифр в результирующих строках, как показано в следующем примере.
decimal value = 16309.5436m;
string result = String.Format("{0,12:#.00000} {0,12:0,000.00} {0,12:000.00#}",
value);
Console.WriteLine(result);
// The example displays the following output:
// 16309.54360 16,309.54 16309.544
let value = 16309.5436m
String.Format("{0,12:#.00000} {0,12:0,000.00} {0,12:000.00#}", value)
|> printfn "%s"
// The example displays the following output:
// 16309.54360 16,309.54 16309.544
Module Example8
Public Sub Main()
Dim value As Decimal = 16309.5436D
Dim result As String = String.Format("{0,12:#.00000} {0,12:0,000.00} {0,12:000.00#}",
value)
Console.WriteLine(result)
End Sub
End Module
' The example displays the following output:
' 16309.54360 16,309.54 16309.544
Как управлять числом целочисленных цифр?
По умолчанию операции форматирования отображают только ненулевые целые числа. При форматировании целых чисел можно использовать описатель точности со строками стандартного формата "D" и "X" для управления числом цифр.
int value = 1326;
string result = String.Format("{0,10:D6} {0,10:X8}", value);
Console.WriteLine(result);
// The example displays the following output:
// 001326 0000052E
open System
let value = 1326
String.Format("{0,10:D6} {0,10:X8}", value)
|> printfn "%s"
// The example displays the following output:
// 001326 0000052E
Module Example10
Public Sub Main()
Dim value As Integer = 1326
Dim result As String = String.Format("{0,10:D6} {0,10:X8}", value)
Console.WriteLine(result)
End Sub
End Module
' The example displays the following output:
' 001326 0000052E
Целое число или число с плавающей запятой можно дополнить начальными нулями для создания строки результата с указанным числом разрядов с помощью описателя пользовательского числового формата "0", как показано в следующем примере.
int value = 16342;
string result = String.Format("{0,18:00000000} {0,18:00000000.000} {0,18:000,0000,000.0}",
value);
Console.WriteLine(result);
// The example displays the following output:
// 00016342 00016342.000 0,000,016,342.0
open System
let value = 16342
String.Format("{0,18:00000000} {0,18:00000000.000} {0,18:000,0000,000.0}", value)
|> printfn "%s"
// The example displays the following output:
// 00016342 00016342.000 0,000,016,342.0
Module Example9
Public Sub Main()
Dim value As Integer = 16342
Dim result As String = String.Format("{0,18:00000000} {0,18:00000000.000} {0,18:000,0000,000.0}",
value)
Console.WriteLine(result)
End Sub
End Module
' The example displays the following output:
' 00016342 00016342.000 0,000,016,342.0
Сколько элементов я могу включить в список форматов?
Нет практического ограничения. Второй параметр Format(IFormatProvider, String, Object[]) метода помечен ParamArrayAttribute атрибутом, что позволяет включать список разделителей или массив объектов в качестве списка форматов.
Как включить литеральные скобки ("{" и "}") в результирующую строку?
Например, как запретить следующему вызову метода вызвать FormatException исключение?
result = String.Format("The text has {0} '{' characters and {1} '}' characters.",
nOpen, nClose);
let result =
String.Format("The text has {0} '{' characters and {1} '}' characters.", nOpen, nClose)
result = String.Format("The text has {0} '{' characters and {1} '}' characters.",
nOpen, nClose)
Одна открывающая или закрывающая фигурная скобка всегда рассматривается как начало или конец элемента форматирования. Чтобы его интерпретировали буквально, необходимо экранирование. Вы экранируете фигурную скобку, добавив еще одну фигурную скобку ("{{" и "}}", а не "{" и "}"), как в следующем вызове метода:
string result;
int nOpen = 1;
int nClose = 2;
result = String.Format("The text has {0} '{{' characters and {1} '}}' characters.",
nOpen, nClose);
Console.WriteLine(result);
let result =
String.Format("The text has {0} '{{' characters and {1} '}}' characters.", nOpen, nClose)
result = String.Format("The text has {0} '{{' characters and {1} '}}' characters.",
nOpen, nClose)
Тем не менее, даже экранированные фигурные скобки легко неправильно интерпретируются. Рекомендуется включить фигурные скобки в список форматов и использовать элементы формата для их вставки в результирующую строку, как показано в следующем примере.
string result;
int nOpen = 1;
int nClose = 2;
result = String.Format("The text has {0} '{1}' characters and {2} '{3}' characters.",
nOpen, "{", nClose, "}");
Console.WriteLine(result);
let result =
String.Format("The text has {0} '{1}' characters and {2} '{3}' characters.", nOpen, "{", nClose, "}")
result = String.Format("The text has {0} '{1}' characters and {2} '{3}' characters.",
nOpen, "{", nClose, "}")
Почему вызов метода String.Format вызывает исключение FormatException?
Наиболее распространенной причиной исключения является то, что индекс элемента формата не соответствует объекту в списке форматов. Обычно это означает, что индексы элементов форматирования были неправильно указаны или вы забыли включить объект в список форматов. При попытке включить неискаченный левый или правый символ фигурной скобки FormatExceptionтакже вызывается. Иногда исключение является результатом опечатки; Например, типичная ошибка заключается в неправильном вводе "[" (левая скобка) вместо "{" (левая скобка).
Если метод Format(System.IFormatProvider,System.String,System.Object[]) поддерживает массивы параметров, почему мой код создает исключение при использовании массива?
Например, следующий код вызывает FormatException исключение:
Random rnd = new Random();
int[] numbers = new int[4];
int total = 0;
for (int ctr = 0; ctr <= 2; ctr++)
{
int number = rnd.Next(1001);
numbers[ctr] = number;
total += number;
}
numbers[3] = total;
Console.WriteLine($"{numbers} + {1} + {2} = {3}");
open System
let rnd = Random()
let mutable total = 0
let numbers = Array.zeroCreate<int> 4
for i = 0 to 2 do
let number = rnd.Next 1001
numbers[i] <- number
total <- total + number
numbers[3] <- total
Console.WriteLine("{0} + {1} + {2} = {3}", numbers)
Imports System.Collections.Generic
Module Example5
Public Sub Main()
Dim rnd As New Random()
Dim numbers(3) As Integer
Dim total As Integer = 0
For ctr = 0 To 2
Dim number As Integer = rnd.Next(1001)
numbers(ctr) = number
total += number
Next
numbers(3) = total
Console.WriteLine("{0} + {1} + {2} = {3}", numbers)
End Sub
End Module
Это проблема разрешения перегрузки компилятора. Так как компилятор не может преобразовать массив целых чисел в массив объектов, он обрабатывает целый массив как один аргумент, поэтому вызывает Format(String, Object) метод. Исключение возникает из-за того, что имеется четыре элемента формата, но только один элемент в списке форматирования.
Так как ни Visual Basic, ни C# не могут преобразовать целый массив в массив объектов, перед вызовом Format(String, Object[]) метода необходимо выполнить преобразование самостоятельно. В следующем примере представлена одна реализация.
Random rnd = new Random();
int[] numbers = new int[4];
int total = 0;
for (int ctr = 0; ctr <= 2; ctr++)
{
int number = rnd.Next(1001);
numbers[ctr] = number;
total += number;
}
numbers[3] = total;
object[] values = new object[numbers.Length];
numbers.CopyTo(values, 0);
Console.WriteLine($"{values} + {1} + {2} = {3}");
open System
let rnd = Random()
let numbers = Array.zeroCreate<int> 4
let mutable total = 0
for i = 0 to 2 do
let number = rnd.Next 1001
numbers[i] <- number
total <- total + number
numbers[3] <- total
let values = Array.zeroCreate<obj> numbers.Length
numbers.CopyTo(values, 0)
Console.WriteLine("{0} + {1} + {2} = {3}", values)
Imports System.Collections.Generic
Module Example6
Public Sub Main()
Dim rnd As New Random()
Dim numbers(3) As Integer
Dim total As Integer = 0
For ctr = 0 To 2
Dim number As Integer = rnd.Next(1001)
numbers(ctr) = number
total += number
Next
numbers(3) = total
Dim values(numbers.Length - 1) As Object
numbers.CopyTo(values, 0)
Console.WriteLine("{0} + {1} + {2} = {3}", values)
End Sub
End Module