複合格式

.NET 複合格式功能會採用物件清單和複合格式字串作為輸入。 複合格式字串是由混合索引替代符號 (Placeholder) 的固定文字所組成 (這些符號稱為對應至清單內物件的格式項目)。 格式作業產生的結果字串是由原始固定文字所組成,這些固定文字混合了清單中代表物件的字串。

重要

如果您使用的語言和語言版本支援,您可以使用「內插字串」,而不使用複合格式字串。 內插字串是包含「插入運算式」的字串。 每個插值的運算式會以運算式的值解析,且在字串指派時,包含在結果字串中。 如需詳細資訊,請參閱 (c # 參考中的字串插補) 和插入字串 (Visual Basic 參考)

下列方法支援複合格式功能:

複合格式字串

複合格式字串和物件清單會當做支援複合格式功能之方法的引數來使用。 複合格式字串是由零個或更多段與一個或多個格式項目混合的固定文字所組成, 固定文字是您選擇的任何文字,而每個格式項目都會對應到清單內的一個物件或 boxed 結構。 複合格式功能將會傳回新的結果字串,其中每一個格式項目都會由清單內對應物件的字串表示來取代。

請考量下列 Format 程式碼片段。

string name = "Fred";
String.Format("Name = {0}, hours = {1:hh}", name, DateTime.Now);
Dim name As String = "Fred"
String.Format("Name = {0}, hours = {1:hh}", name, DateTime.Now)

固定文字是 "Name =" 和 ", hours ="。 格式項目為 "{0}" (其索引為 0,且對應至物件 name) 及 "{1:hh}" (其索引為 1,且對應至物件 DateTime.Now)。

格式項目語法

每個格式項目都會使用下列格式,並由下列元件所組成:

{索引[ , 對齊] [ : 格式字串]}

成對的大括號 ("{" 和 "}") 是必要的。

索引元件

強制的 index 元件 (也稱為參數規範) 是用以識別物件清單中對應項目的數字 (從 0 開始)。 也就是說,參數規範為 0 的格式項目會格式化清單中的第一個物件,而參數規範為 1 的格式項目會格式化清單中的第二個物件,依此類推。 下列範例包含四個參數規範 (編號為 0 到 3),以表示小於 10 的質數:

string primes;
primes = String.Format("Prime numbers less than 10: {0}, {1}, {2}, {3}",
                       2, 3, 5, 7 );
Console.WriteLine(primes);
// The example displays the following output:
//      Prime numbers less than 10: 2, 3, 5, 7
Dim primes As String
primes = String.Format("Prime numbers less than 10: {0}, {1}, {2}, {3}",
                       2, 3, 5, 7)
Console.WriteLine(primes)
' The example displays the following output:
'      Prime numbers less than 10: 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} "。 不是格式項目所參考的物件會被忽略。 FormatException如果參數規範指定超出物件清單範圍的專案,則會在執行時間擲回。

對齊元件

選擇性 alignment 元件為帶正負號的整數,表示慣用的格式化欄位寬度。 如果 alignment 的值小於格式化字串的長度,則會忽略 alignment 並使用格式化字串的長度當做欄位寬度。 如果 alignment 為正數,欄位中的格式化資料會靠右對齊;如果 alignment 為負數,則會靠左對齊。 如果填補有必要,則會使用泛空白字元 (White Space)。 如果指定了 alignment,則需要逗號。

下列範例會定義兩個陣列,一個包含員工的名稱,另一個包含他們在兩週內的工作時數。 複合格式字串會在 20 個字元的欄位中,將名稱靠左對齊,並且在 5 個字元的欄位中,將其工作時數靠右對齊。 請注意,"N1" 標準格式字串也會用來格式化具有一個小數位數的時數。

using System;

public class Example
{
   public static void Main()
   {
      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 ctr = 0; ctr < names.Length; ctr++)
         Console.WriteLine("{0,-20} {1,5:N1}", names[ctr], hours[ctr]);
   }
}
// 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
Module Example
    Public Sub Main()
        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}", "Name", "Hours")
        Console.WriteLine()
        For ctr As Integer = 0 To names.Length - 1
            Console.WriteLine("{0,-20} {1,5:N1}", names(ctr), hours(ctr))
        Next
    End Sub
End Module
' 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 元件是一個格式字串,適用於將格式化的物件類型。 如果對應的物件為數值,指定標準或自訂的數值格式字串;如果對應的物件為 DateTime 物件,指定標準或自訂的日期和時間格式字串;或者,如果對應的物件為列舉值,指定列舉格式字串。 如果未指定 formatString,則會使用數值、日期和時間或列舉類型的一般 ("G") 格式規範。 如果指定 formatString,則需要冒號。

下表列出 .NET 類別庫中支援一組預先定義格式字串的類型或類別類型,並提供列出所支援格式字串之主題的連結。 請注意,字串格式是一種可延伸機制,可讓為所有現有類型定義新的格式字串,以及定義一組應用程式定義類型所支援的格式字串。 如需詳細資訊,請參閱 IFormattableICustomFormatter 介面主題。

類型或類型分類 請參閱
日期和時間類型 (DateTimeDateTimeOffset) 標準日期和時間格式字串

自訂日期和時間格式字串
列舉類型 (衍生自 System.Enum 的所有類型) 列舉格式字串
數字類型 (BigIntegerByteDecimalDoubleInt16Int32Int64SByteSingleUInt16UInt32UInt64) 標準數值格式字串 (部分機器翻譯)

自訂數值格式字串
Guid Guid.ToString(String)
TimeSpan 標準 TimeSpan 格式字串

自訂 TimeSpan 格式字串

逸出大括號

左右大括號會被解譯成格式項目的開頭與結尾。 因此,您必須使用逸出序列 (Escape Sequence),才能顯示字面上的左右大括號。 請在固定文字中指定兩個左邊的大括號 ("{{"),以顯示一個左邊的大括號 ("{"),或者指定兩個右邊的大括號 ("}}") 來顯示一個右邊的大括號 ("}")。 格式項目中的括號會以它們出現的順序依序解譯, 但是不支援解譯巢狀大括號。

解譯逸出括號的方式,可能會造成無法預期的結果。 例如,格式項目 "{{{0:D}}}" 原本是要顯示一個左邊大括號、一個格式化為十進位的數值和一個右邊大括號。 然而,格式項目實際會以下列方式來解譯:

  1. 前面兩個左邊大括號 ("{{") 逸出,產生一個左邊大括號。

  2. 接下來的三個字元 ("{0:") 會解譯成格式項目的開頭。

  3. 再下一個字元 ("D") 可能解譯成十進位 (Decimal) 標準數值格式規範,但後面兩個逸出的右邊大括號 ("}}") 會產生一個大括號。 由於結果字串 ("D}") 並非標準的數值格式規範,因此,結果字串會被解譯成自訂格式字串,表示會顯示成常值字串 "D}"。

  4. 最後的大括號 ("}") 會被解譯成格式項目的結尾。

  5. 最後顯示的結果會是常值字串 "{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 實作,它會快取長達複合格式方法的呼叫持續時間。

參數清單中每個對應於格式項目的值都會轉換為字串,如下所示:

  1. 如果要格式化的值是 null,則會傳回空字串 String.Empty

  2. 如果可以使用 ICustomFormatter 實作,則執行階段會呼叫其 Format 方法。 它會將格式項目的 formatString 值 (如果有的話) 傳遞給方法;如果沒有,則會將 null 連同 IFormatProvider 實作一起傳遞。 如果 ICustomFormatter.Format 方法呼叫傳回 null,則會繼續執行到下一個步驟;否則,會傳回 ICustomFormatter.Format 呼叫的結果。

  3. 如果值實作 IFormattable 介面,則會呼叫介面的 ToString(String, IFormatProvider) 方法。 如果格式項目中有 formatString 值的話,就會將該值傳遞給方法;如果沒有的話,則會傳遞 nullIFormatProvider 引數的判斷如下:

  4. 呼叫類型的無參數 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")

假設目前日期是五月的星期四,前面範例中兩個字串的值在美國英文文化特性中都是 Thursday May

Console.WriteLine 會公開與 String.Format 相同的功能。 這兩種方法唯一的差別在於,String.Format 會以字串形式傳回結果,而 Console.WriteLine 則會將結果寫入至與 Console 物件關聯的輸出資料流。 下列範例使用 Console.WriteLine 方法,將 MyInt 的值格式化為貨幣值。

int MyInt = 100;
Console.WriteLine("{0:C}", MyInt);
// The example displays the following output
// if en-US is the current culture:
//        $100.00
Dim MyInt As Integer = 100
Console.WriteLine("{0:C}", MyInt)
' 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 myFName = "Fred";
string myLName = "Opals";
int myInt = 100;
string FormatFName = String.Format("First Name = |{0,10}|", myFName);
string FormatLName = String.Format("Last Name = |{0,10}|", myLName);
string FormatPrice = String.Format("Price = |{0,10:C}|", myInt);
Console.WriteLine(FormatFName);
Console.WriteLine(FormatLName);
Console.WriteLine(FormatPrice);
Console.WriteLine();

FormatFName = String.Format("First Name = |{0,-10}|", myFName);
FormatLName = String.Format("Last Name = |{0,-10}|", myLName);
FormatPrice = String.Format("Price = |{0,-10:C}|", myInt);
Console.WriteLine(FormatFName);
Console.WriteLine(FormatLName);
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 myFName As String = "Fred"
Dim myLName As String = "Opals"

Dim myInt As Integer = 100
Dim FormatFName As String = String.Format("First Name = |{0,10}|", myFName)
Dim FormatLName As String = String.Format("Last Name = |{0,10}|", myLName)
Dim FormatPrice As String = String.Format("Price = |{0,10:C}|", myInt)
Console.WriteLine(FormatFName)
Console.WriteLine(FormatLName)
Console.WriteLine(FormatPrice)
Console.WriteLine()

FormatFName = String.Format("First Name = |{0,-10}|", myFName)
FormatLName = String.Format("Last Name = |{0,-10}|", myLName)
FormatPrice = String.Format("Price = |{0,-10:C}|", myInt)
Console.WriteLine(FormatFName)
Console.WriteLine(FormatLName)
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   |

另請參閱