Share via


格式化型別

格式化是將類別、結構或列舉值的執行個體轉換成字串表示的過程,通常是為了將結果字串展示予使用者,或是為了將字串藉還原序列化方式還原成原始的資料型別。 這種轉換可能面臨幾項挑戰:

  • 值的內部儲存方式不見得反映出使用者想要的檢視方式。 例如,電話號碼可能以 8009999999 的格式儲存,但這並不太符合使用者的閱讀習慣。 應該改以顯示成 800-999-9999。

  • 物件轉換後的字串表示有時候並不符合直覺。 例如,Temperature 物件或 Person 物件的字串表示應該為何種格式,就不是那麼清楚。

  • 值的格式通常需要符合文化特性。 例如,如果應用程式需要使用數字來表達貨幣值,則數值字串應該包含目前文化特性的貨幣符號、群組分隔符號 (即大部分文化特性中的千位分隔符號) 和小數點符號。

  • 應用程式可能需要以不同的方式來顯示相同的值。 例如,應用程式在表示列舉成員時,在做法上可能是顯示其名稱的字串表示,或顯示其基礎值。

注意事項注意事項

格式化會將某種型別的值轉換為字串表示。剖析是格式化的反向操作。剖析作業會從資料型別的字串表示來建立資料型別的執行個體。如需將字串轉換為其他資料型別的詳細資訊,請參閱剖析字串

.NET Framework 提供豐富的格式化支援,可滿足開發人員的這些需求。

本概觀包含下列各節:

  • .NET Framework 中的格式化

  • 使用 ToString 方法的預設格式

  • 覆寫 ToString 方法

  • ToString 方法和格式字串

  • 格式提供者和 IFormatProvider 介面

  • IFormattable 介面

  • 複合格式

  • 使用 ICustomFormatter 的自訂格式

  • 相關主題

  • 參考資料

.NET Framework 中的格式化

格式化機制的基礎在於 Object.ToString 方法的預設實作,這將於本主題稍後的使用 ToString 方法的預設格式一節中討論。 不過,.NET Framework 提供幾種方式來修改和擴充其預設格式化支援。 這些需求包括下列各項:

  • 覆寫 Object.ToString 方法來自訂物件值的字串表示。 如需詳細資訊,請參閱本主題稍後的覆寫 ToString 方法一節。

  • 定義格式規範,格式規範讓物件值的字串表示可以採用多種形式。 例如,下列陳述式中的 "X" 格式規範會將整數轉換為十六進位值的字串表示。

    Console.WriteLine(integerValue.ToString("X"))   ' Displays EB98.
    
    Console.WriteLine(integerValue.ToString("X"));   // Displays EB98.
    

    如需格式規範的詳細資訊,請參閱 ToString 方法和格式字串一節。

  • 透過格式提供者來採用特定文化特性的格式化慣例。 例如,下列陳述式會使用 en-US 文化特性的格式化慣例來顯示貨幣值。

    Console.WriteLine(cost.ToString("C", New System.Globalization.CultureInfo("en-US")))
    ' The example displays the following output:
    '       $1,632.54
    
    Console.WriteLine(cost.ToString("C", 
                      new System.Globalization.CultureInfo("en-US")));   
    // The example displays the following output:
    //       $1,632.54
    

    如需以格式提供者進行格式化的詳細資訊,請參閱格式提供者和 IFormatProvider 介面一節。

  • 實作 IFormattable 介面,以同時支援使用 Convert 類別和複合格式來轉換字串。 如需詳細資訊,請參閱 IFormattable 介面一節。

  • 使用複合格式將值的字串表示嵌入更大的字串中。 如需詳細資訊,請參閱複合格式一節。

  • 實作 ICustomFormatterIFormatProvider 來提供完整的自訂格式解決方案。 如需詳細資訊,請參閱使用 ICustomFormatter 的自訂格式一節。

下列各節會討論這些將物件轉換為其字串表示的方法。

回到頁首

使用 ToString 方法的預設格式

每個衍生自 System.Object 的型別都會自動繼承無參數的 ToString 方法,這個方法預設會傳回型別的名稱。 下列範例示範預設的 ToString 方法。 範例中會定義一個不具任何實作的 Automobile 類別。 當執行個體化這個類別並呼叫這個類別的 ToString 方法時,會顯示這個類別的型別名稱。

Public Class Automobile
   ' No implementation. All members are inherited from Object.
End Class

Module Example
   Public Sub Main()
      Dim firstAuto As New Automobile()
      Console.WriteLine(firstAuto)
   End Sub
End Module
' The example displays the following output:
'       Automobile
using System;

public class Automobile
{
   // No implementation. All members are inherited from Object.
}

public class Example
{
   public static void Main()
   {
      Automobile firstAuto = new Automobile();
      Console.WriteLine(firstAuto);
   }
}
// The example displays the following output:
//       Automobile

因為除介面以外的所有其他型別都會衍生自 Object,所以您的自訂類別或結構會自動被賦予此功能。 不過,預設的 ToString 方法提供的功能有限:它雖然可以識別型別,但無法提供型別執行個體的任何資訊。 若要提供物件的字串表示來表達該物件的相關資訊,您必須覆寫 ToString 方法。

注意事項注意事項

結構會繼承自 ValueType,而後者又會衍生自 Object。雖然 ValueType 會覆寫 Object.ToString,但實作方法是相同的。

回到頁首

覆寫 ToString 方法

顯示型別的名稱通常用途不大,亦無法讓您型別的使用者藉以區分不同的執行個體。 不過,您可以覆寫 ToString 方法,以更實用的方式表示物件的值。 下列範例定義 Temperature 物件,並覆寫其 ToString 方法來顯示攝氏溫度。

Public Class Temperature
   Private temp As Decimal

   Public Sub New(temperature As Decimal)
      Me.temp = temperature
   End Sub

   Public Overrides Function ToString() As String
      Return Me.temp.ToString("N1") + "°C"   
   End Function
End Class

Module Example
   Public Sub Main()
      Dim currentTemperature As New Temperature(23.6d)
      Console.WriteLine("The current temperature is {0}.", currentTemperature)
   End Sub
End Module
' The example displays the following output:
'       The current temperature is 23.6°C.
using System;

public class Temperature
{
   private decimal temp;

   public Temperature(decimal temperature)
   {
      this.temp = temperature;   
   }

   public override string ToString()
   {
      return this.temp.ToString("N1") + "°C";
   }
}

public class Example
{
   public static void Main()
   {
      Temperature currentTemperature = new Temperature(23.6m);
      Console.WriteLine("The current temperature is {0}.", currentTemperature);
   }
}
// The example displays the following output:
//       The current temperature is 23.6°C.

在 .NET Framework 中,每個基本值型別的 ToString 方法都已經過覆寫來顯示物件的值,而非物件的名稱。 下表顯示各基本型別如何覆寫 ToString 方法。 請注意,大部分經過覆寫的方法都會呼叫 ToString 方法的另一個多載,並且將 "G" 格式規範 (此規範定義此型別的一般格式) 和 IFormatProvider 物件 (此物件表示目前文化特性) 傳遞至這個多載。

型別

ToString 覆寫

Boolean

傳回 Boolean.TrueStringBoolean.FalseString

Byte

呼叫 Byte.ToString("G", NumberFormatInfo.CurrentInfo),以根據目前的文化特性來格式化 Byte 值。

Char

以字串形式傳回字元。

DateTime

呼叫 DateTime.ToString("G", DatetimeFormatInfo.CurrentInfo),以根據對目前的文化特性來格式化日期和時間值。

Decimal

呼叫 Decimal.ToString("G", NumberFormatInfo.CurrentInfo),以根據目前的文化特性來格式化 Decimal 值。

Double

呼叫 Double.ToString("G", NumberFormatInfo.CurrentInfo),以根據目前的文化特性來格式化 Double 值。

Int16

呼叫 Int16.ToString("G", NumberFormatInfo.CurrentInfo),以根據目前的文化特性來格式化 Int16 值。

Int32

呼叫 Int32.ToString("G", NumberFormatInfo.CurrentInfo),以根據目前的文化特性來格式化 Int32 值。

Int64

呼叫 Int64.ToString("G", NumberFormatInfo.CurrentInfo),以根據目前的文化特性來格式化 Int64 值。

SByte

呼叫 SByte.ToString("G", NumberFormatInfo.CurrentInfo),以根據目前的文化特性來格式化 SByte 值。

Single

呼叫 Single.ToString("G", NumberFormatInfo.CurrentInfo),以根據目前的文化特性來格式化 Single 值。

UInt16

呼叫 UInt16.ToString("G", NumberFormatInfo.CurrentInfo),以根據目前的文化特性來格式化 UInt16 值。

UInt32

呼叫 UInt32.ToString("G", NumberFormatInfo.CurrentInfo),以根據目前的文化特性來格式化 UInt32 值。

UInt64

呼叫 UInt64.ToString("G", NumberFormatInfo.CurrentInfo),以根據目前的文化特性來格式化 UInt64 值。

回到頁首

ToString 方法和格式字串

當物件只有單一字串表示時,使用預設 ToString 方法或覆寫 ToString 都沒有問題。 不過,物件的值通常有多種表示。 例如,溫度可以用華氏、攝氏或開氏溫度表示。 同樣地,整數值 10 可以用許多方式表示,包括 10、10.0、1.0e01 或 $10.00。

為了讓單一值可以具有多種字串表示,.NET Framework 使用格式字串。 格式字串是包含一個或多個預先定義之格式規範的字串,這個字串是單一字元或一組字元,用於定義 ToString 方法應採用的輸出格式。 然後,格式字串會當做參數傳遞至物件的 ToString 方法,以決定如何呈現該物件的值的字串表示。

.NET Framework 中所有的數字型別、日期和時間型別,以及列舉型別,都支援一組預先定義的格式規範。 您也可以利用格式字串定義多種字串表示給您應用程式中定義的資料型別。

標準格式字串

標準格式字串包含單一格式規範 (一個字母字元,定義套用此規範之物件的字串表示) 和選擇性的精確度規範 (這個規範影響結果字串中顯示的位數)。 如果省略或不支援精確度規範,則標準格式規範與標準格式字串無異。

.NET Framework 針對所有數值型別、所有日期和時間型別,以及所有列舉型別,都定義一組標準格式規範。 例如,這些分類每個都支援 "G" 標準格式規範 (這個規範定義該型別之值的一般字串表示)。

列舉型別的標準格式字串直接控制了值的字串表示。 傳遞給列舉值的 ToString 方法的格式字串決定了該值是以其字串名稱 ("G" 和 "F" 格式規範)、基礎整數值 ("D" 格式規範),還是十六進位值 ("X" 格式規範) 來顯示。 下列範例示範如何使用標準格式字串來格式化 DayOfWeek 列舉值。

Dim thisDay As DayOfWeek = DayOfWeek.Monday
Dim formatStrings() As String = {"G", "F", "D", "X"}

For Each formatString As String In formatStrings
   Console.WriteLine(thisDay.ToString(formatString))
Next
' The example displays the following output:
'       Monday
'       Monday
'       1
'       00000001
DayOfWeek thisDay = DayOfWeek.Monday;
string[] formatStrings = {"G", "F", "D", "X"};

foreach (string formatString in formatStrings)
   Console.WriteLine(thisDay.ToString(formatString));
// The example displays the following output:
//       Monday
//       Monday
//       1
//       00000001

如需列舉格式字串的詳細資訊,請參閱列舉型別格式字串

數值型別的標準格式字串定義出的結果字串之確切外觀通常是由一個或多個屬性值所控制。 例如,"C" 格式規範會將數字格式化為貨幣值。 當您將 "C" 格式規範做為唯一參數來呼叫 ToString 方法時,會使用目前文化特性之 NumberFormatInfo 物件中的下列屬性值來定義數值的字串表示:

此外,數值格式字串也可以包含精確度規範。 這個規範的意義視搭配使用的格式字串而定,但通常是表示結果字串中應該顯示的總位數或小數位數。 例如,下列範例會使用 "X4" 標準數值字串和精確度規範,建立具有四個十六進位數字的字串值。

Dim byteValues() As Byte = { 12, 163, 255 }
For Each byteValue As Byte In byteValues
   Console.WriteLine(byteValue.ToString("X4"))
Next
' The example displays the following output:
'       000C
'       00A3
'       00FF
byte[] byteValues = { 12, 163, 255 };
foreach (byte byteValue in byteValues)
   Console.WriteLine(byteValue.ToString("X4"));
// The example displays the following output:
//       000C
//       00A3
//       00FF

如需標準數值格式字串的詳細資訊,請參閱標準數值格式字串

日期和時間值的標準格式字串是特定 DateTimeFormatInfo 屬性所儲存之自訂格式字串的別名。 例如,以 "D" 格式規範來呼叫日期和時間值的 ToString 方法,將會使用目前文化特性之 DateTimeFormatInfo.LongDatePattern 屬性中所儲存的自訂格式字串來顯示日期和時間 (如需自訂格式字串的詳細資訊,請參閱下一節)。下列範例示範這種關聯性。

Imports System.Globalization

Module Example
   Public Sub Main()
      Dim date1 As Date = #6/30/2009#
      Console.WriteLine("D Format Specifier:     {0:D}", date1)
      Dim longPattern As String = CultureInfo.CurrentCulture.DateTimeFormat.LongDatePattern
      Console.WriteLine("'{0}' custom format string:     {1}", _
                        longPattern, date1.ToString(longPattern))
   End Sub
End Module
' The example displays the following output when run on a system whose
' current culture is en-US:
'    D Format Specifier:     Tuesday, June 30, 2009
'    'dddd, MMMM dd, yyyy' custom format string:     Tuesday, June 30, 2009
using System;
using System.Globalization;

public class Example
{
   public static void Main()
   {
      DateTime date1 = new DateTime(2009, 6, 30);
      Console.WriteLine("D Format Specifier:     {0:D}", date1);
      string longPattern = CultureInfo.CurrentCulture.DateTimeFormat.LongDatePattern;
      Console.WriteLine("'{0}' custom format string:     {1}", 
                        longPattern, date1.ToString(longPattern));
   }
}
// The example displays the following output when run on a system whose
// current culture is en-US:
//    D Format Specifier:     Tuesday, June 30, 2009
//    'dddd, MMMM dd, yyyy' custom format string:     Tuesday, June 30, 2009

如需標準日期和時間格式字串的詳細資訊,請參閱標準日期和時間格式字串

對於應用程式定義的物件,您也可以使用標準格式字串來定義由該物件的 ToString(String) 方法所產生的字串表示。 您可以定義您的物件所支援的特定標準格式規範,並且決定這項規範是否區分大小寫。 您對 ToString(String) 方法的實作應該要能支援:

  • "G" 格式規範,表示物件的慣用或通用格式。 您物件的 ToString 方法的無參數多載應該要呼叫這個方法的 ToString(String) 多載,並且將 "G" 標準格式字串傳遞給這個方法。

  • 支援等於 null 參考 (在 Visual Basic 中為 Nothing) 的格式規範。 等於 null 參考的格式規範應該要視為相當於 "G" 格式規範。

例如,Temperature 類別可以在內部以攝氏儲存溫度,並透過格式規範以攝氏、華氏和開氏溫度來表示 Temperature 物件的值。 下列範例提供一個實例。

Public Class Temperature
   Private m_Temp As Decimal

   Public Sub New(temperature As Decimal)
      Me.m_Temp = temperature
   End Sub

   Public ReadOnly Property Celsius() As Decimal
      Get
         Return Me.m_Temp
      End Get   
   End Property

   Public ReadOnly Property Kelvin() As Decimal
      Get
         Return Me.m_Temp + 273.15d   
      End Get
   End Property

   Public ReadOnly Property Fahrenheit() As Decimal
      Get
         Return Math.Round(CDec(Me.m_Temp * 9 / 5 + 32), 2)
      End Get      
   End Property

   Public Overrides Function ToString() As String
      Return Me.ToString("C")
   End Function

   Public Overloads Function ToString(format As String) As String  
      ' Handle null or empty string.
      If String.IsNullOrEmpty(format) Then format = "C"
      ' Remove spaces and convert to uppercase.
      format = format.Trim().ToUpperInvariant()      

      ' Convert temperature to Fahrenheit and return string.
      Select Case format
         Case "F"
            Return Me.Fahrenheit.ToString("N2") & " °F"
         ' Convert temperature to Kelvin and return string.
         Case "K"
            Return Me.Kelvin.ToString("N2") & " K"
         ' Return temperature in Celsius.
         Case "C"
            Return Me.Celsius.ToString("N2") & " °C"
         Case Else
            Throw New FormatException(String.Format("The '{0}' format string is not supported.", format))
      End Select      
   End Function
End Class

Public Module Example
   Public Sub Main()
      Dim temp1 As New Temperature(0d)
      Console.WriteLine(temp1.ToString())
      Console.WriteLine(temp1.ToString("C"))
      Console.WriteLine(temp1.ToString("F"))
      Console.WriteLine(temp1.ToString("K"))
      Dim temp2 As New Temperature(-40d)
      Console.WriteLine(temp2.ToString())
      Console.WriteLine(temp2.ToString("C"))
      Console.WriteLine(temp2.ToString("F"))
      Console.WriteLine(temp2.ToString("K"))
      Dim temp3 As New Temperature(16d)
      Console.WriteLine(temp3.ToString())
      Console.WriteLine(temp3.ToString("C"))
      Console.WriteLine(temp3.ToString("F"))
      Console.WriteLine(temp3.ToString("K"))

      Console.WriteLine(String.Format("The temperature is now {0:F}.", temp3))
   End Sub
End Module
' The example displays the following output:
'       0.00 °C
'       0.00 °C
'       32.00 °F
'       273.15 K
'       -40.00 °C
'       -40.00 °C
'       -40.00 °F
'       233.15 K
'       16.00 °C
'       16.00 °C
'       60.80 °F
'       289.15 K
'       The temperature is now 16.00 °C.
public class Temperature
{
   private decimal m_Temp;

   public Temperature(decimal temperature)
   {
      this.m_Temp = temperature;
   }

   public decimal Celsius
   {
      get { return this.m_Temp; }
   }

   public decimal Kelvin
   {
      get { return this.m_Temp + 273.15m; }   
   }

   public decimal Fahrenheit
   {
      get { return Math.Round(((decimal) (this.m_Temp * 9 / 5 + 32)), 2); }
   }

   public override string ToString()
   {
      return this.ToString("C");
   }

   public string ToString(string format)
   {  
      // Handle null or empty string.
      if (String.IsNullOrEmpty(format)) format = "C";
      // Remove spaces and convert to uppercase.
      format = format.Trim().ToUpperInvariant();      

      // Convert temperature to Fahrenheit and return string.
      switch (format)
      {
         // Convert temperature to Fahrenheit and return string.
         case "F":
            return this.Fahrenheit.ToString("N2") + " °F";
         // Convert temperature to Kelvin and return string.
         case "K":
            return this.Kelvin.ToString("N2") + " K";
         // return temperature in Celsius.
         case "C":
            return this.Celsius.ToString("N2") + " °C";
         default:
            throw new FormatException(String.Format("The '{0}' format string is not supported.", format));
      }      
   }
}

public class Example
{
   public static void Main()
   {
      Temperature temp1 = new Temperature(0m);
      Console.WriteLine(temp1.ToString());
      Console.WriteLine(temp1.ToString("C"));
      Console.WriteLine(temp1.ToString("F"));
      Console.WriteLine(temp1.ToString("K"));
      Temperature temp2 = new Temperature(-40m);
      Console.WriteLine(temp2.ToString());
      Console.WriteLine(temp2.ToString("C"));
      Console.WriteLine(temp2.ToString("F"));
      Console.WriteLine(temp2.ToString("K"));
      Temperature temp3 = new Temperature(16m);
      Console.WriteLine(temp3.ToString());
      Console.WriteLine(temp3.ToString("C"));
      Console.WriteLine(temp3.ToString("F"));
      Console.WriteLine(temp3.ToString("K"));

      Console.WriteLine(String.Format("The temperature is now {0:F}.", temp3));
   }
}
// The example displays the following output:
//       0.00 °C
//       0.00 °C
//       32.00 °F
//       273.15 K
//       -40.00 °C
//       -40.00 °C
//       -40.00 °F
//       233.15 K
//       16.00 °C
//       16.00 °C
//       60.80 °F
//       289.15 K
//       The temperature is now 16.00 °C.

回到頁首

自訂格式字串

除了標準格式字串,.NET Framework 也為數值及日期和時間值定義了自訂格式字串。 自訂格式字串由一個或多個自訂格式規範組成,這些規範定義了值的字串表示。 例如,自訂日期和時間格式字串 "yyyy/mm/dd hh:mm:ss.ffff t zzz" 會將日期轉換為其字串表示,以 en-US 文化特性而言為 "2008/11/15 07:45:00.0000 P -08:00" 形式。 同樣地,自訂格式字串 "0000" 會將整數值 12 轉換為 "0012"。 如需完整的自訂格式字串清單,請參閱自訂日期和時間格式字串自訂數值格式字串

如果格式字串由單一自訂格式規範組成,則應該在格式規範前面加上百分比 (%) 符號,以避免與標準格式規範產生混淆。 下列範例會使用 "M" 自訂格式規範來顯示特定日期的一位數或兩位數月份。

Dim date1 As Date = #09/08/2009#
Console.WriteLine(date1.ToString("%M"))      ' Displays 9
DateTime date1 = new DateTime(2009, 9, 8);
Console.WriteLine(date1.ToString("%M"));       // Displays 9

日期和時間值的許多標準格式字串都是自訂格式字串 (這些自訂格式字串由 DateTimeFormatInfo 物件的屬性所定義) 的別名。 自訂格式字串也提供極大的彈性,來提供應用程式定義的數值或日期和時間值格式。 您可以將多個自訂格式規範結合成單一自訂格式字串,以自訂您的數值及日期和時間值結果字串。 下列範例定義的自訂格式字串,會在月份名稱、日期和年後面顯示加上括號的星期。

Dim customFormat As String = "MMMM dd, yyyy (dddd)"
Dim date1 As Date = #8/28/2009#
Console.WriteLine(date1.ToString(customFormat))   
' The example displays the following output if run on a system
' whose language is English:
'       August 28, 2009 (Friday)      
string customFormat = "MMMM dd, yyyy (dddd)";
DateTime date1 = new DateTime(2009, 8, 28);
Console.WriteLine(date1.ToString(customFormat));   
// The example displays the following output if run on a system
// whose language is English:
//       August 28, 2009 (Friday)      

雖然標準格式字串通常能夠為應用程式定義的型別解決大部分的格式需求,但您也可以定義自訂格式規範來格式化您的型別。

回到頁首

格式提供者和 IFormatProvider 介面

雖然格式規範可讓您自訂物件的格式,但如果要為物件產生有意義的字串表示,您通常還需要其他格式設定資訊。 例如,如果要使用 "C" 標準格式字串或自訂格式字串 (例如 "$ #,#.00") 將數字格式化為貨幣值,您至少還需要有正確的貨幣符號、群組分隔符號和小數分隔符號的相關資訊。 在 .NET Framework 中,這些額外的資訊是透過 IFormatProvider 介面取得,而這個介面會做為參數放在數字型別及日期和時間型別之 ToString 方法的一個或多個多載中。 下列範例示範以三種不同的 IFormatProvider 物件來格式化物件的字串表示時的情形。

Imports System.Globalization

Public Module Example
   Public Sub Main()
      Dim value As Decimal = 1603.42d
      Console.WriteLine(value.ToString("C3", New CultureInfo("en-US")))
      Console.WriteLine(value.ToString("C3", New CultureInfo("fr-FR")))
      Console.WriteLine(value.ToString("C3", New CultureInfo("de-DE")))
   End Sub
End Module
' The example displays the following output:
'       $1,603.420
'       1 603,420 €
'       1.603,420 €
using System;
using System.Globalization;

public class Example
{
   public static void Main()
   {
      decimal value = 1603.42m;
      Console.WriteLine(value.ToString("C3", new CultureInfo("en-US")));
      Console.WriteLine(value.ToString("C3", new CultureInfo("fr-FR")));
      Console.WriteLine(value.ToString("C3", new CultureInfo("de-DE")));
   }
}
// The example displays the following output:
//       $1,603.420
//       1 603,420 €
//       1.603,420 €

IFormatProvider 介面包含一個 GetFormat(Type) 方法,這個方法具有單一參數來指定可提供格式設定資訊之物件的型別。 如果這個方法可以提供該型別的物件,則會傳回該物件。 否則會傳回 null 參考 (在 Visual Basic 中為 Nothing)。

IFormatProvider.GetFormat 是一種回呼方法。 當您呼叫包含 IFormatProvider 參數的 ToString 方法多載時,這個多載會呼叫該 IFormatProvider 物件的 GetFormat 方法。 GetFormat 方法負責將提供必要格式設定資訊的物件 (由其 formatType 參數指定),傳回給 ToString 方法。

有幾個格式化或字串轉換方法都包含 IFormatProvider 型別的參數,但通常呼叫方法時,會忽略這個參數的值。 下表列出一些使用這個參數的格式化方法,以及這些方法傳遞至 IFormatProvider.GetFormat 方法的 Type 物件的型別。

方法

formatType 參數的型別

數字型別的 ToString 方法

System.Globalization.NumberFormatInfo

日期和時間型別的 ToString 方法

System.Globalization.DateTimeFormatInfo

String.Format

System.ICustomFormatter

StringBuilder.AppendFormat

System.ICustomFormatter

注意事項注意事項

數字型別及日期和時間型別的 ToString 方法都含有多載,而其中只有某些多載會包含 IFormatProvider 參數。如果方法沒有 IFormatProvider 型別的參數,則會改以傳遞 CultureInfo.CurrentCulture 屬性所傳回的物件。例如,呼叫預設的 Int32.ToString() 方法最終會產生如下的方法呼叫:Int32.ToString("G", System.Globalization.CultureInfo.CurrentCulture)。

.NET Framework 提供三個實作 IFormatProvider 的類別:

您也可以實作自己的格式提供者來取代上述任何一個類別。 不過,您實作的 GetFormat 方法如果必須提供格式設定資訊給 ToString 方法,則必須傳回上表所列之型別的物件。

回到頁首

IFormattable 介面

以格式字串和 IFormatProvider 參數來多載 ToString 方法的型別,通常也會實作 IFormattable 介面。 這個介面具有單一成員 IFormattable.ToString(String, IFormatProvider),這個成員同時包含格式字串和格式提供者做為參數。

針對您的應用程式定義的類別來實作 IFormattable 介面有兩項好處:

下列範例定義一個實作 IFormattable 介面的 Temperature 類別。 這個類別支援 "C" 或 "G" 格式規範來顯示攝氏溫度、支援 "F" 格式規範來顯示華氏溫度,也支援 "K" 格式規範來顯示絕對溫度。

Imports System.Globalization

Public Class Temperature : Implements IFormattable
   Private m_Temp As Decimal

   Public Sub New(temperature As Decimal)
      Me.m_Temp = temperature
   End Sub

   Public ReadOnly Property Celsius() As Decimal
      Get
         Return Me.m_Temp
      End Get   
   End Property

   Public ReadOnly Property Kelvin() As Decimal
      Get
         Return Me.m_Temp + 273.15d   
      End Get
   End Property

   Public ReadOnly Property Fahrenheit() As Decimal
      Get
         Return Math.Round(CDec(Me.m_Temp * 9 / 5 + 32), 2)
      End Get      
   End Property

   Public Overrides Function ToString() As String
      Return Me.ToString("G", Nothing)
   End Function

   Public Overloads Function ToString(format As String) As String
      Return Me.ToString(format, Nothing)
   End Function

   Public Overloads Function ToString(format As String, provider As IFormatProvider) As String _  
      Implements IFormattable.ToString

      ' Handle null or empty arguments.
      If String.IsNullOrEmpty(format) Then format = "G"
      ' Remove any white space and convert to uppercase.
      format = format.Trim().ToUpperInvariant()

      If provider Is Nothing Then provider = NumberFormatInfo.CurrentInfo

      Select Case format
         ' Convert temperature to Fahrenheit and return string.
         Case "F"
            Return Me.Fahrenheit.ToString("N2", provider) & "°F"
         ' Convert temperature to Kelvin and return string.
         Case "K"
            Return Me.Kelvin.ToString("N2", provider) & "K"
         ' Return temperature in Celsius.
         Case "C", "G"
            Return Me.Celsius.ToString("N2", provider) & "°C"
         Case Else
            Throw New FormatException(String.Format("The '{0}' format string is not supported.", format))
      End Select      
   End Function
End Class
using System;
using System.Globalization;

public class Temperature : IFormattable
{
   private decimal m_Temp;

   public Temperature(decimal temperature)
   {
      this.m_Temp = temperature;
   }

   public decimal Celsius
   {
      get { return this.m_Temp; }
   }

   public decimal Kelvin
   {
      get { return this.m_Temp + 273.15m; }   
   }

   public decimal Fahrenheit
   {
      get { return Math.Round((decimal) this.m_Temp * 9 / 5 + 32, 2); }
   }

   public override string ToString()
   {
      return this.ToString("G", null);
   }

   public string ToString(string format)
   {
      return this.ToString(format, null);
   }

   public string ToString(string format, IFormatProvider provider)  
   {
      // Handle null or empty arguments.
      if (String.IsNullOrEmpty(format)) format = "G";
      // Remove any white space and convert to uppercase.
      format = format.Trim().ToUpperInvariant();

      if (provider == null) provider = NumberFormatInfo.CurrentInfo;

      switch (format)
      {
         // Convert temperature to Fahrenheit and return string.
         case "F":
            return this.Fahrenheit.ToString("N2", provider) + "°F";
         // Convert temperature to Kelvin and return string.
         case "K":
            return this.Kelvin.ToString("N2", provider) + "K";
         // Return temperature in Celsius.
         case "C":
         case "G":
            return this.Celsius.ToString("N2", provider) + "°C";
         default:
            throw new FormatException(String.Format("The '{0}' format string is not supported.", format));
      }      
   }
}

下列範例會執行個體化 Temperature 物件。 然後呼叫 ToString 方法,並使用數個複合格式字串來取得 Temperature 物件的不同字串表示。 其中每個方法又呼叫 Temperature 類別的 IFormattable 實作。

Public Module Example
   Public Sub Main()
      Dim temp1 As New Temperature(22d)
      Console.WriteLine(Convert.ToString(temp1, New CultureInfo("ja-JP")))
      Console.WriteLine("Temperature: {0:K}", temp1)
      Console.WriteLine("Temperature: {0:F}", temp1)
      Console.WriteLine(String.Format(New CultureInfo("fr-FR"), "Temperature: {0:F}", temp1)) 
   End Sub
End Module
' The example displays the following output:
'       22.00°C
'       Temperature: 295.15°K
'       Temperature: 71.60°F
'       Temperature: 71,60°F
public class Example
{
   public static void Main()
   {
      Temperature temp1 = new Temperature(22m);
      Console.WriteLine(Convert.ToString(temp1, new CultureInfo("ja-JP")));
      Console.WriteLine("Temperature: {0:K}", temp1);
      Console.WriteLine("Temperature: {0:F}", temp1);
      Console.WriteLine(String.Format(new CultureInfo("fr-FR"), "Temperature: {0:F}", temp1));
   }
}
// The example displays the following output:
//       22.00°C
//       Temperature: 295.15°K
//       Temperature: 71.60°F
//       Temperature: 71,60°F

回到頁首

複合格式

某些方法 (例如 String.FormatStringBuilder.AppendFormat) 支援複合格式。 複合格式字串是一種範本,可傳回由零個、一個或更多物件的字串表示所組成的單一字串。 複合格式字串中的每個物件都以有索引的格式項目來表示。 格式項目的索引對應至其所表示的物件在方法的參數清單中的位置。 索引以零為起始。 例如,在下列對 String.Format 方法的呼叫中,第一個格式項目 {0:D} 由 thatDate 的字串表示所取代、第二個格式項目 {1} 由 item1 的字串表示所取代,而第三個格式項目 {2:C2} 由 item1.Value 的字串表示所取代。

result = String.Format("On {0:d}, the inventory of {1} was worth {2:C2}.", _
                       thatDate, item1, item1.Value)
Console.WriteLine(result)                            
' The example displays output like the following if run on a system
' whose current culture is en-US:
'       On 5/1/2009, the inventory of WidgetA was worth $107.44.
result = String.Format("On {0:d}, the inventory of {1} was worth {2:C2}.", 
                       thatDate, item1, item1.Value);
Console.WriteLine(result);                            
// The example displays output like the following if run on a system
// whose current culture is en-US:
//       On 5/1/2009, the inventory of WidgetA was worth $107.44.

如需複合格式的詳細資訊,請參閱複合格式

回到頁首

使用 ICustomFormatter 的自訂格式

某些複合格式方法 (例如 String.Format(IFormatProvider, String, Object[])StringBuilder.AppendFormat(IFormatProvider, String, Object[])) 包含支援自訂格式的格式提供者參數。 呼叫格式化方法時,會將表示 ICustomFormatter 介面的 Type 物件傳遞至格式提供者的 GetFormat 方法。 然後,GetFormat 方法負責傳回 ICustomFormatter 實作,這個實作提供自訂格式。

ICustomFormatter 介面具有單一方法 Format(String, Object, IFormatProvider),複合格式化方法會自動針對複合格式字串中的每個格式項目,各呼叫一次這個方法。 Format(String, Object, IFormatProvider) 方法具有三個參數:格式字串 (表示格式項目中的 formatString 引數)、要格式化的物件,以及提供格式化服務的 IFormatProvider 物件。 實作 ICustomFormatter 的物件通常也會實作 IFormatProvider,所以這最後一個參數是對自訂格式化類別的參考。 方法會傳回要格式化之物件的自訂格式化字串表示。 如果方法無法格式化物件,則應該傳回 null 參考 (在 Visual Basic 中為 Nothing)。

下列範例提供一個名為 ByteByByteFormatter 的 ICustomFormatter 實作,這個實作會將整數值顯示為一連串由兩位數十六進位值再加上一個空格所組成的數列。

Public Class ByteByByteFormatter : 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, arg As Object, 
                          formatProvider As IFormatProvider) As String _
                          Implements ICustomFormatter.Format

      If Not formatProvider.Equals(Me) Then Return Nothing

      ' Handle only hexadecimal format string.
      If Not fmt.StartsWith("X") Then 
            Return Nothing
      End If

      ' Handle only integral types.
      If Not typeof arg Is Byte AndAlso
         Not typeof arg Is Int16 AndAlso
         Not typeof arg Is Int32 AndAlso
         Not typeof arg Is Int64 AndAlso
         Not typeof arg Is SByte AndAlso
         Not typeof arg Is UInt16 AndAlso
         Not typeof arg Is UInt32 AndAlso
         Not typeof arg Is UInt64 Then _
            Return Nothing

      Dim bytes() As Byte = BitConverter.GetBytes(arg)
      Dim output As String = Nothing

      For ctr As Integer = bytes.Length - 1 To 0 Step -1
         output += String.Format("{0:X2} ", bytes(ctr))   
      Next

      Return output.Trim()
   End Function
End Class
public class ByteByByteFormatter : 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 (! formatProvider.Equals(this)) return null;

      // Handle only hexadecimal format string.
      if (! format.StartsWith("X")) return null;

      byte[] bytes;
      string output = null;

      // Handle only integral types.
      if (arg is Byte) 
         bytes = BitConverter.GetBytes((Byte) arg);
      else if (arg is Int16)
         bytes = BitConverter.GetBytes((Int16) arg);
      else if (arg is Int32)
         bytes = BitConverter.GetBytes((Int32) arg);
      else if (arg is Int64)   
         bytes = BitConverter.GetBytes((Int64) arg);
      else if (arg is SByte)
         bytes = BitConverter.GetBytes((SByte) arg);
      else if (arg is UInt16)
         bytes = BitConverter.GetBytes((UInt16) arg);
      else if (arg is UInt32)
         bytes = BitConverter.GetBytes((UInt32) arg);
      else if (arg is UInt64)
         bytes = BitConverter.GetBytes((UInt64) arg);
      else
         return null;

      for (int ctr = bytes.Length - 1; ctr >= 0; ctr--)
         output += String.Format("{0:X2} ", bytes[ctr]);   

      return output.Trim();
   }
}

下列範例會使用 ByteByByteFormatter 類別來格式化整數值。 請注意,ICustomFormatter.Format 方法在第二個 String.Format(IFormatProvider, String, Object[]) 方法呼叫中被呼叫不只一次,且第三個方法呼叫中使用預設 NumberFormatInfo 提供者,因為 ByteByByteFormatter.Format 方法無法辨認 "N0" 格式字串而傳回 null 參考 (在 Visual Basic 中為 Nothing)。

Public Module Example
   Public Sub Main()
      Dim value As Long = 3210662321 
      Dim value1 As Byte = 214
      Dim value2 As Byte = 19

      Console.WriteLine((String.Format(New ByteByByteFormatter(), "{0:X}", value)))
      Console.WriteLine((String.Format(New ByteByByteFormatter(), "{0:X} And {1:X} = {2:X} ({2:000})", 
                                      value1, value2, value1 And value2)))                                
      Console.WriteLine(String.Format(New ByteByByteFormatter(), "{0,10:N0}", value))
   End Sub
End Module
' The example displays the following output:
'       00 00 00 00 BF 5E D1 B1
'       00 D6 And 00 13 = 00 12 (018)
'       3,210,662,321
public class Example
{
   public static void Main()
   {
      long value = 3210662321; 
      byte value1 = 214;
      byte value2 = 19;

      Console.WriteLine(String.Format(new ByteByByteFormatter(), "{0:X}", value));
      Console.WriteLine(String.Format(new ByteByByteFormatter(), "{0:X} And {1:X} = {2:X} ({2:000})", 
                                      value1, value2, value1 & value2));                                
      Console.WriteLine(String.Format(new ByteByByteFormatter(), "{0,10:N0}", value));
   }
}
// The example displays the following output:
//       00 00 00 00 BF 5E D1 B1
//       00 D6 And 00 13 = 00 12 (018)
//       3,210,662,321

回到頁首

相關主題

標題

定義

標準數值格式字串

說明建立數值常用之字串表示的標準格式字串。

自訂數值格式字串

說明建立應用程式專屬數值格式的自訂格式字串。

標準日期和時間格式字串

說明建立 DateTime 值之常用字串表示的標準格式字串。

自訂日期和時間格式字串

說明建立應用程式專屬 DateTime 值格式的自訂格式字串。

標準 TimeSpan 格式字串

說明建立時間間隔之常用字串表示的標準格式字串。

自訂 TimeSpan 格式字串

說明建立應用程式專屬數值格式的自訂格式字串。

列舉型別格式字串

說明用來建立列舉值之字串表示的標準格式字串。

複合格式

描述如何將一個或更多的格式化值嵌入字串。 字串可以隨後顯示在主控台 (Console) 或寫入資料流。

執行格式化作業

列出各主題,提供執行特定格式設定作業的逐步指示。

剖析字串

說明如何將物件初始化為這些物件的字串表示所描述的值。 剖析是格式化的反向作業。

回到頁首

參考資料

System.IFormattable

System.IFormatProvider

System.ICustomFormatter