.NET 複合格式設定功能會採用物件清單和複合格式字串做為輸入。 複合格式字串是由固定文字與被稱為格式項目的索引佔位元混合而成。 這些格式項目對應於清單中的物件。 格式作業產生的結果字串是由原始固定文字所組成,這些固定文字混合了清單中代表物件的字串。
這很重要
如果您使用的語言及其版本支持插補字串,則可以使用它們,而不是使用複合格式字串。 插補字串包含 插補運算式。 每個插補表達式都會先計算出其值,然後在指派字串時將其包含在結果字串中。 如需詳細資訊,請參閱 字串插補(C# 參考) 和 插補字串 (Visual Basic 參考)。
下列方法支援複合格式設定功能:
- String.Format,它會傳回格式化的結果字串。
- StringBuilder.AppendFormat,它會將格式化的結果字串附加至 StringBuilder 物件。
- Console.WriteLine 方法的某些重載會將格式化後的結果字串顯示於主控台。
- TextWriter.WriteLine 方法的某些多載,會將格式化的結果字串寫入數據流或檔案。 衍生自 TextWriter的類別,例如 StreamWriter 和 HtmlTextWriter,也會共用這項功能。
- Debug.WriteLine(String, Object[]),它會將格式化的訊息輸出至追蹤接聽程式。
- Trace.TraceError(String, Object[])、Trace.TraceInformation(String, Object[])和 Trace.TraceWarning(String, Object[]) 方法,可將格式化的訊息輸出至追蹤接聽程式。
- TraceSource.TraceInformation(String, Object[]) 方法,會寫入資訊方法來追蹤監聽器。
複合格式字串
複合格式字串和物件清單會當做支持複合格式功能之方法的自變數使用。 複合格式字串由零個或多個固定文字段落和一個或多個格式項目交織組成。 固定的文字是您選擇的任何字串,而且每個格式項目都對應到清單中的物件或盒裝結構。 每個物件的字串表示會取代對應的格式專案。
請考慮下列 Format 代碼段:
string.Format("Name = {0}, hours = {1:hh}", "Fred", DateTime.Now);
String.Format("Name = {0}, hours = {1:hh}", "Fred", DateTime.Now)
固定文字為 Name = ,, hours = 。 格式項目是 {0},其索引 0 對應於字串文字 "Fred",以及 {1:hh},其索引 1 對應於 的 DateTime.Now值。
格式項目語法
每個格式項目都會使用下列格式,並由下列元件所組成:
{index[,width][:formatString]}
成對的大括號 ({ 和 }) 是必要的。
索引元件
強制 index 元件也稱為參數規範,是從 0 開始的數位,可識別物件清單中的對應專案。 也就是說,參數指定符為 0 的格式項目格式化清單中的第一個物件。 在格式清單中,參數規範為 1 的格式項指定格式化第二個物件,依此類推。 下列範例包含四個參數規範,編號為零到三,以表示小於 10 的質數:
string primes = string.Format("Four prime numbers: {0}, {1}, {2}, {3}",
2, 3, 5, 7);
Console.WriteLine(primes);
// The example displays the following output:
// Four prime numbers: 2, 3, 5, 7
Dim primes As String = String.Format("Four prime numbers: {0}, {1}, {2}, {3}",
2, 3, 5, 7)
Console.WriteLine(primes)
'The example displays the following output
' Four prime numbers 2, 3, 5, 7
多個格式項目可以藉由指定相同的參數規範,參考物件清單中的相同元素。 例如,您可以藉由指定複合格式字串,例如 "0x{0:X} {0:E} {0:N}",以十六進位、科學和數位格式格式化相同的數值,如下列範例所示:
string multiple = string.Format("0x{0:X} {0:E} {0:N}",
Int64.MaxValue);
Console.WriteLine(multiple);
// The example displays the following output:
// 0x7FFFFFFFFFFFFFFF 9.223372E+018 9,223,372,036,854,775,807.00
Dim multiple As String = String.Format("0x{0:X} {0:E} {0:N}",
Int64.MaxValue)
Console.WriteLine(multiple)
'The example displays the following output
' 0x7FFFFFFFFFFFFFFF 9.223372E+018 9,223,372,036,854,775,807.00
每個格式項目都可以引用清單中的任何物件。 例如,如果有三個物件,您可以藉由指定複合格式字串,例如 {1} {0} {2}來格式化第二個、第一個和第三個物件。 格式項目未參考的物件會被忽略。 若參數指定符指定物件範圍外的項目,則執行時會拋出 A FormatException 。
寬度元件
選擇性 width 元件是帶正負號的整數,表示慣用格式化的字段寬度。 如果的值 width 小於格式化字串的長度, width 則會忽略 ,而格式化字串的長度會當做字段寬度使用。 如果 width 為正數,則字段中格式化的數據會靠右對齊,如果 width 為負數則靠左對齊。 如果需要填補,則會使用空格符。 如果 width 已指定,則需要逗號。
下列範例會定義兩個陣列,一個數位包含員工的名稱,另一個陣列則包含他們工作兩周的時數。 複合格式字串會靠左對齊 20 個字元欄位中的名稱,並在 5 個字元欄位中靠右對齊其時數。 “N1” 標準格式字串會將小時格式化為一個小數位數。
string[] names = { "Adam", "Bridgette", "Carla", "Daniel",
"Ebenezer", "Francine", "George" };
decimal[] hours = { 40, 6.667m, 40.39m, 82,
40.333m, 80, 16.75m };
Console.WriteLine("{0,-20} {1,5}\n", "Name", "Hours");
for (int counter = 0; counter < names.Length; counter++)
Console.WriteLine("{0,-20} {1,5:N1}", names[counter], hours[counter]);
// The example displays the following output:
// Name Hours
//
// Adam 40.0
// Bridgette 6.7
// Carla 40.4
// Daniel 82.0
// Ebenezer 40.3
// Francine 80.0
// George 16.8
Dim names As String() = {"Adam", "Bridgette", "Carla", "Daniel",
"Ebenezer", "Francine", "George"}
Dim hours As Decimal() = {40, 6.667D, 40.39D, 82,
40.333D, 80, 16.75D}
Console.WriteLine("{0,-20} {1,5}\n", "Name", "Hours")
For counter = 0 To names.Length - 1
Console.WriteLine("{0,-20} {1,5:N1}", names(counter), hours(counter))
Next
'The example displays the following output
' Name Hours
'
' Adam 40.0
' Bridgette 6.7
' Carla 40.4
' Daniel 82.0
' Ebenezer 40.3
' Francine 80.0
' George 16.8
格式化字串元件
選擇性 formatString 元件是適合格式化物件類型的格式字串。 您可以指定:
如果未指定 formatString,則會使用數值、日期和時間或列舉類型的一般(“G”)格式規範。 指定 formatString 時,冒號是必需的。
下表列出 .NET 類別庫中支援一組預先定義格式字串的類型或類別,並提供列出支援格式字串之文章的連結。 字串格式設定是一種可延伸的機制,可讓您為所有現有類型定義新的格式字串,以及定義應用程式定義型別所支援的格式字串集。
如需詳細資訊,請參閱 IFormattable 和 ICustomFormatter 介面文章。
| 類型或類型類別 | 看! |
|---|---|
| 日期與時間類型 (DateTime、 DateTimeOffset) |
標準日期和時間格式字串 自訂日期和時間格式字串 |
| 列舉型別(衍生自 System.Enum的所有型別) | 列舉格式字串 |
| 數值類型(BigInteger、Byte、Decimal、Double、Int16、Int32、Int64、SByte、Single、UInt16、UInt32、UInt64) |
標準數值格式字串 自訂數值格式字串 |
| Guid | Guid.ToString(String) |
| TimeSpan |
標準 TimeSpan 格式字串 自定義 TimeSpan 格式字串 |
跳脫字元處理大括號
左大括弧和右大括弧被解讀為格式項目的開始和結束符號。 若要顯示常值左大括弧或右大括弧,您必須使用跳脫序列。 在固定文字中指定兩個左大括弧({{),以顯示一個左大括弧({),或兩個右大括弧(}}),以顯示一個右大括弧(})。
格式專案中的逃脫大括弧在 .NET 和 .NET Framework 之間會以不同的方式解析。
.NET
大括號可以在格式項目周圍逸出。 例如,請考慮格式專案 {{{0:D}}},其用於顯示左括號、一個格式化為十進位的數值,以及右括號。 格式項目會以下列方式解釋:
- 前兩個左大括弧(
{{)會逸出,併產生一個左大括弧。 - 接下來的三個字元(
{0:)會解譯為格式專案的開頭。 - 下一個字元 (
D) 會解譯為十進位標準數值格式規範。 - 下一個大括弧 (
}) 會解譯為格式項目的結尾。 - 最後兩個右大括弧會逸出,併產生一個右大括弧。
- 顯示的最終結果是常值字串,
{6324}。
int value = 6324;
string output = string.Format("{{{0:D}}}", value);
Console.WriteLine(output);
// The example displays the following output:
// {6324}
Dim value As Integer = 6324
Dim output As String = String.Format("{{{0:D}}}", value)
Console.WriteLine(output)
'The example displays the following output
' {6324}
.NET Framework
格式專案中的大括弧會按照它們出現的順序被解譯。 不支援解譯巢狀大括號。
對轉義大括號的解讀方式可能導致非預期的結果。 例如,請考慮格式專案 {{{0:D}}},其用於顯示左括號、一個格式化為十進位的數值,以及右括號。 不過,格式項目會以下列方式解釋:
- 前兩個左大括弧(
{{)會逸出,併產生一個左大括弧。 - 接下來的三個字元(
{0:)會解譯為格式專案的開頭。 - 下一個字元 (
D) 會解譯為十進位標準數值格式指定元,但接下來的兩個逸出大括弧 (}}) 會產生單一大括弧。 由於生成的字串(D})不是標準的數值格式規範,因此該字串被解釋為自定義格式字串,即顯示字串D}。 - 最後一個大括弧 (
}) 會解譯為格式項目的結尾。 - 顯示的最終結果是常值字串,
{D}。 未顯示要格式化的數值。
int value = 6324;
string output = string.Format("{{{0:D}}}",
value);
Console.WriteLine(output);
// The example displays the following output:
// {D}
Dim value As Integer = 6324
Dim output As String = String.Format("{{{0:D}}}",
value)
Console.WriteLine(output)
'The example displays the following output:
' {D}
撰寫程式碼以避免錯誤解譯跳脫的大括號和格式項的方法之一,就是分別格式化大括號和格式項。 也就是說,在第一個格式作業中,顯示文字左大括號。 在下一個操作中顯示格式項目的結果,並且在最後一個操作中顯示字面右大括號。 下列範例說明此方法:
int value = 6324;
string output = string.Format("{0}{1:D}{2}",
"{", value, "}");
Console.WriteLine(output);
// The example displays the following output:
// {6324}
Dim value As Integer = 6324
Dim output As String = String.Format("{0}{1:D}{2}",
"{", value, "}")
Console.WriteLine(output)
'The example displays the following output:
' {6324}
處理順序
如果對複合格式方法的呼叫包含其值不是 IFormatProvider的 null 自變數,運行時間會呼叫其 IFormatProvider.GetFormat 方法來要求 ICustomFormatter 實作。 如果方法可以傳回一個 ICustomFormatter 實作,則會在呼叫複合格式化方法時被快取。
對應至格式項目的參數清單中每個值都會轉換成字串,如下所示:
如果要格式化的值是
null,則會傳回空字串 String.Empty。如果有可用的 ICustomFormatter 實作,運行時間會呼叫其 Format 方法。 執行階段會將格式項目的
formatString值傳遞給方法,如果formatString不存在,則傳遞 。 運行時間也會將 IFormatProvider 實作傳遞至該方法。 如果呼叫 ICustomFormatter.Format 方法傳回null,則執行會繼續進行下一個步驟。 否則,將會傳回呼叫 ICustomFormatter.Format 的結果。如果值實作 IFormattable 介面,則會呼叫 介面的 ToString(String, IFormatProvider) 方法。 如果格式項目中存在一個,則會將
formatString值傳遞至方法。 否則,null會被傳遞。 IFormatProvider 自變數的判斷方式如下:針對數值,如果呼叫具有非 null IFormatProvider 自變數的複合格式方法,運行時間會從其 NumberFormatInfo 方法要求 IFormatProvider.GetFormat 物件。 如果無法提供一個,當引數的值是
null,或複合格式方法沒有 IFormatProvider 引數時,則會使用目前文化特性的 NumberFormatInfo 物件。針對日期和時間值,如果呼叫具有非 null IFormatProvider 自變數的複合格式方法,運行時間會從其 DateTimeFormatInfo 方法要求 IFormatProvider.GetFormat 物件。 在下列情況下,會改用目前文化特性的 DateTimeFormatInfo 物件:
- IFormatProvider.GetFormat 方法無法提供 DateTimeFormatInfo 物件。
- 自變數的值
null。 - 複合格式方法沒有 IFormatProvider 參數。
對於其他類型的物件,如果使用 IFormatProvider 自變數呼叫複合格式方法,則會將其值直接傳遞至 IFormattable.ToString 實作。 否則,
null被傳遞至 IFormattable.ToString 實作。
無參數的
ToString方法被呼叫,該方法會覆寫 Object.ToString() 或繼承其基類的行為。 在此情況下,如果格式專案中有formatString元件,則會忽略其指定的格式字串。
在執行上述步驟之後,會套用對齊方式。
程式碼範例
下列範例顯示一個使用複合格式建立的字串,另一個字元串則使用物件的 ToString 方法建立。 這兩種類型的格式都會產生對等的結果。
string formatString1 = string.Format("{0:dddd MMMM}", DateTime.Now);
string formatString2 = DateTime.Now.ToString("dddd MMMM");
Dim formatString1 As String = String.Format("{0:dddd MMMM}", DateTime.Now)
Dim formatString2 As String = DateTime.Now.ToString("dddd MMMM")
假設目前日期是 5 月的星期四,上述範例中這兩個字串在美式英語文化中的值都是 Thursday May。
Console.WriteLine 公開與 String.Format相同的功能。 這兩種方法之間的唯一差異在於 String.Format 會以字串傳回其結果,而 Console.WriteLine 將結果寫入與 Console 對象相關聯的輸出數據流。 下列範例會使用 Console.WriteLine 方法,將 myNumber 的值格式化為貨幣值:
int myNumber = 100;
Console.WriteLine($"{myNumber:C}");
// The example displays the following output
// if en-US is the current culture:
// $100.00
Dim myNumber As Integer = 100
Console.WriteLine("{0:C}", myNumber)
'The example displays the following output
'if en-US Is the current culture:
' $100.00
下列範例示範如何格式化多個物件,包括以兩種不同的方式格式化一個物件:
string myName = "Fred";
Console.WriteLine(string.Format("Name = {0}, hours = {1:hh}, minutes = {1:mm}",
myName, DateTime.Now));
// Depending on the current time, the example displays output like the following:
// Name = Fred, hours = 11, minutes = 30
Dim myName As String = "Fred"
Console.WriteLine(String.Format("Name = {0}, hours = {1:hh}, minutes = {1:mm}",
myName, DateTime.Now))
'Depending on the current time, the example displays output Like the following:
' Name = Fred, hours = 11, minutes = 30
下列範例示範格式化中的寬度用法。 格式化的引數會放在垂直線(|)之間,以便突出顯示其對齊效果。
string firstName = "Fred";
string lastName = "Opals";
int myNumber = 100;
string formatFirstName = string.Format("First Name = |{0,10}|", firstName);
string formatLastName = string.Format("Last Name = |{0,10}|", lastName);
string formatPrice = string.Format("Price = |{0,10:C}|", myNumber);
Console.WriteLine(formatFirstName);
Console.WriteLine(formatLastName);
Console.WriteLine(formatPrice);
Console.WriteLine();
formatFirstName = string.Format("First Name = |{0,-10}|", firstName);
formatLastName = string.Format("Last Name = |{0,-10}|", lastName);
formatPrice = string.Format("Price = |{0,-10:C}|", myNumber);
Console.WriteLine(formatFirstName);
Console.WriteLine(formatLastName);
Console.WriteLine(formatPrice);
// The example displays the following output on a system whose current
// culture is en-US:
// First Name = | Fred|
// Last Name = | Opals|
// Price = | $100.00|
//
// First Name = |Fred |
// Last Name = |Opals |
// Price = |$100.00 |
Dim firstName As String = "Fred"
Dim lastName As String = "Opals"
Dim myNumber As Integer = 100
Dim formatFirstName As String = String.Format("First Name = |{0,10}|", firstName)
Dim formatLastName As String = String.Format("Last Name = |{0,10}|", lastName)
Dim formatPrice As String = String.Format("Price = |{0,10:C}|", myNumber)
Console.WriteLine(formatFirstName)
Console.WriteLine(formatLastName)
Console.WriteLine(formatPrice)
Console.WriteLine()
formatFirstName = String.Format("First Name = |{0,-10}|", firstName)
formatLastName = String.Format("Last Name = |{0,-10}|", lastName)
formatPrice = String.Format("Price = |{0,-10:C}|", myNumber)
Console.WriteLine(formatFirstName)
Console.WriteLine(formatLastName)
Console.WriteLine(formatPrice)
'The example displays the following output on a system whose current
'culture Is en-US:
' First Name = | Fred|
' Last Name = | Opals|
' Price = | $100.00|
'
' First Name = |Fred |
' Last Name = |Opals |
' Price = |$100.00 |