Omówienie: Jak formatować liczby, daty, wyliczenia i inne typy na platformie .NET

Formatowanie to proces konwertowania wystąpienia klasy lub struktury lub wartości wyliczenia na reprezentację ciągu. Celem jest wyświetlenie wynikowego ciągu dla użytkowników lub deserializacji go później w celu przywrócenia oryginalnego typu danych. W tym artykule przedstawiono mechanizmy formatowania zapewniane przez platformę .NET.

Uwaga

Analizowanie jest odwrotnością formatowania. Operacja analizowania tworzy wystąpienie typu danych na podstawie reprezentacji ciągu. Aby uzyskać więcej informacji, zobacz Analizowanie ciągów. Aby uzyskać informacje na temat serializacji i deserializacji, zobacz Serializacja na platformie .NET.

Podstawowy mechanizm formatowania to domyślna implementacja Object.ToString metody, która została omówiona w sekcji Formatowanie domyślne przy użyciu metody ToString w dalszej części tego tematu. Jednak platforma .NET udostępnia kilka sposobów modyfikowania i rozszerzania domyślnej obsługi formatowania. Należą do nich:

  • Object.ToString Zastąpienie metody w celu zdefiniowania niestandardowej reprezentacji ciągu wartości obiektu. Aby uzyskać więcej informacji, zobacz sekcję Przesłoń metodę ToString w dalszej części tego tematu.

  • Definiowanie specyfikatorów formatu, które umożliwiają reprezentację ciągu wartości obiektu w wielu formularzach. Na przykład specyfikator formatu "X" w poniższej instrukcji konwertuje liczbę całkowitą na reprezentację ciągu wartości szesnastkowej.

    int integerValue = 60312;
    Console.WriteLine(integerValue.ToString("X"));   // Displays EB98.
    
    Dim integerValue As Integer = 60312
    Console.WriteLine(integerValue.ToString("X"))   ' Displays EB98.
    

    Aby uzyskać więcej informacji na temat specyfikatorów formatu, zobacz sekcję ToString Method and Format Strings (Metody i formatowania ciągów).

  • Używanie dostawców formatu do implementowania konwencji formatowania określonej kultury. Na przykład poniższa instrukcja wyświetla wartość waluty przy użyciu konwencji formatowania kultury en-US.

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

    Aby uzyskać więcej informacji na temat formatowania z dostawcami formatów, zobacz sekcję Dostawcy formatu.

  • Implementowanie interfejsu IFormattable w celu obsługi konwersji ciągów przy użyciu klasy i formatowania złożonego Convert . Aby uzyskać więcej informacji, zobacz sekcję Interfejs IFormattable .

  • Używanie formatowania złożonego do osadzania reprezentacji ciągu wartości w większym ciągu. Aby uzyskać więcej informacji, zobacz sekcję Formatowanie złożone .

  • Przy użyciu interpolacji ciągów bardziej czytelna składnia osadzania reprezentacji ciągu wartości w większym ciągu. Aby uzyskać więcej informacji, zobacz Interpolacja ciągów.

  • Implementowanie ICustomFormatter i IFormatProvider zapewnienie kompletnego niestandardowego rozwiązania do formatowania. Aby uzyskać więcej informacji, zobacz sekcję Custom Formatting with ICustomFormatter (Formatowanie niestandardowe przy użyciu formatu ICustomFormatter ).

W poniższych sekcjach przedstawiono te metody konwertowania obiektu na reprezentację ciągu.

Formatowanie domyślne przy użyciu metody ToString

Każdy typ pochodzący z System.Object programu automatycznie dziedziczy metodę bez ToString parametrów, która domyślnie zwraca nazwę typu. Poniższy przykład ilustruje metodę domyślną ToString . Definiuje klasę o nazwie Automobile , która nie ma implementacji. Po utworzeniu wystąpienia klasy i wywołaniu jej ToString metody zostanie wyświetlona jego nazwa typu. Należy pamiętać, że ToString metoda nie jest jawnie wywoływana w przykładzie. Metoda Console.WriteLine(Object) niejawnie wywołuje metodę ToString obiektu przekazanego do niego jako argument.

using System;

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

public class Example9
{
   public static void Main()
   {
      Automobile firstAuto = new Automobile();
      Console.WriteLine(firstAuto);
   }
}
// The example displays the following output:
//       Automobile
Public Class Automobile
    ' No implementation. All members are inherited from Object.
End Class

Module Example9
    Public Sub Main9()
        Dim firstAuto As New Automobile()
        Console.WriteLine(firstAuto)
    End Sub
End Module
' The example displays the following output:
'       Automobile

Ostrzeżenie

Począwszy od Windows 8.1, środowisko wykonawcze systemu Windows zawiera IStringable interfejs z pojedynczą metodą IStringable.ToString, która zapewnia obsługę formatowania domyślnego. Zalecamy jednak, aby typy zarządzane nie implementować interfejsu IStringable . Aby uzyskać więcej informacji, zobacz sekcję "środowisko wykonawcze systemu Windows i IStringable interfejs" na stronie referencyjnejObject.ToString.

Ponieważ wszystkie typy inne niż interfejsy pochodzą z Objectprogramu , ta funkcja jest automatycznie dostarczana do niestandardowych klas lub struktur. Jednak funkcjonalność oferowana przez metodę domyślną ToString jest ograniczona: chociaż identyfikuje typ, nie może podać żadnych informacji o wystąpieniu typu. Aby podać reprezentację ciągu obiektu, który zawiera informacje o tym obiekcie, należy zastąpić metodę ToString .

Uwaga

Struktury dziedziczą z ValueTypeklasy , która z kolei pochodzi z Objectklasy . Chociaż ValueType zastępuje Object.ToString, jego implementacja jest identyczna.

Zastąpij metodę ToString

Wyświetlanie nazwy typu jest często ograniczone i nie zezwala użytkownikom typów na odróżnienie jednego wystąpienia od innego. Można jednak zastąpić metodę ToString , aby zapewnić bardziej przydatną reprezentację wartości obiektu. Poniższy przykład definiuje obiekt i zastępuje jego ToString metodę Temperature w celu wyświetlenia temperatury w stopniach Celsjusza.

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 Example12
{
    public static void Main()
    {
        Temperature currentTemperature = new Temperature(23.6m);
        Console.WriteLine($"The current temperature is {currentTemperature}");
    }
}
// The example displays the following output:
//       The current temperature is 23.6°C.
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 Example13
    Public Sub Main13()
        Dim currentTemperature As New Temperature(23.6D)
        Console.WriteLine("The current temperature is " +
                          currentTemperature.ToString())
    End Sub
End Module
' The example displays the following output:
'       The current temperature is 23.6°C.

Na platformie .NET ToString metoda każdego typu wartości pierwotnej została zastąpiona w celu wyświetlenia wartości obiektu zamiast jego nazwy. W poniższej tabeli przedstawiono przesłonięcia dla każdego typu pierwotnego. Należy pamiętać, że większość przesłonięć metod wywołuje kolejne przeciążenie ToString metody i przekazuje go specyfikator formatu "G", który definiuje ogólny format dla jego typu i IFormatProvider obiekt, który reprezentuje bieżącą kulturę.

Typ Przesłonięcia toString
Boolean Zwraca wartość Boolean.TrueString lub Boolean.FalseString.
Byte Wywołuje, Byte.ToString("G", NumberFormatInfo.CurrentInfo) aby sformatować Byte wartość bieżącej kultury.
Char Zwraca znak jako ciąg.
DateTime Wywołania DateTime.ToString("G", DatetimeFormatInfo.CurrentInfo) służące do formatowania wartości daty i godziny dla bieżącej kultury.
Decimal Wywołuje, Decimal.ToString("G", NumberFormatInfo.CurrentInfo) aby sformatować Decimal wartość bieżącej kultury.
Double Wywołuje, Double.ToString("G", NumberFormatInfo.CurrentInfo) aby sformatować Double wartość bieżącej kultury.
Int16 Wywołuje, Int16.ToString("G", NumberFormatInfo.CurrentInfo) aby sformatować Int16 wartość bieżącej kultury.
Int32 Wywołuje, Int32.ToString("G", NumberFormatInfo.CurrentInfo) aby sformatować Int32 wartość bieżącej kultury.
Int64 Wywołuje, Int64.ToString("G", NumberFormatInfo.CurrentInfo) aby sformatować Int64 wartość bieżącej kultury.
SByte Wywołuje, SByte.ToString("G", NumberFormatInfo.CurrentInfo) aby sformatować SByte wartość bieżącej kultury.
Single Wywołuje, Single.ToString("G", NumberFormatInfo.CurrentInfo) aby sformatować Single wartość bieżącej kultury.
UInt16 Wywołuje, UInt16.ToString("G", NumberFormatInfo.CurrentInfo) aby sformatować UInt16 wartość bieżącej kultury.
UInt32 Wywołuje, UInt32.ToString("G", NumberFormatInfo.CurrentInfo) aby sformatować UInt32 wartość bieżącej kultury.
UInt64 Wywołuje, UInt64.ToString("G", NumberFormatInfo.CurrentInfo) aby sformatować UInt64 wartość bieżącej kultury.

Ciągi tostring i ciągi formatu

Poleganie na metodzie domyślnej ToString lub zastępowaniu ToString jest odpowiednie, gdy obiekt ma jedną reprezentację ciągu. Jednak wartość obiektu często ma wiele reprezentacji. Na przykład temperatura może być wyrażona w stopniach Fahrenheit, stopni Celsjusza lub kelvins. Podobnie wartość całkowita 10 może być reprezentowana na wiele sposobów, w tym 10, 10,0, 1,0e01 lub 10,00 USD.

Aby włączyć jedną wartość, aby mieć wiele reprezentacji ciągów, platforma .NET używa ciągów formatu. Ciąg formatu to ciąg zawierający co najmniej jeden wstępnie zdefiniowany specyfikator formatu, które są pojedynczymi znakami lub grupami znaków, które definiują sposób ToString formatowania danych wyjściowych metody. Ciąg formatu jest następnie przekazywany jako parametr do metody obiektu i określa sposób wyświetlania ciągu wartości tego obiektu ToString .

Wszystkie typy liczbowe, typy daty i godziny oraz typy wyliczenia na platformie .NET obsługują wstępnie zdefiniowany zestaw specyfikatorów formatu. Możesz również użyć ciągów formatu, aby zdefiniować wiele reprezentacji ciągów typów danych zdefiniowanych przez aplikację.

Standardowe ciągi formatu

Ciąg formatu standardowego zawiera specyfikator pojedynczego formatu, który jest znakiem alfabetycznym definiującym reprezentację ciągu obiektu, do którego jest stosowany, wraz z opcjonalnym specyfikatorem dokładności, który wpływa na liczbę cyfr wyświetlanych w ciągu wynikowym. Jeśli specyfikator dokładności zostanie pominięty lub nie jest obsługiwany, specyfikator formatu standardowego jest odpowiednikiem standardowego ciągu formatu.

Platforma .NET definiuje zestaw standardowych specyfikatorów formatu dla wszystkich typów liczbowych, wszystkich typów daty i godziny oraz wszystkich typów wyliczenia. Na przykład każda z tych kategorii obsługuje specyfikator formatu standardowego "G", który definiuje ogólną reprezentację ciągu wartości tego typu.

Standardowe ciągi formatu dla typów wyliczenia bezpośrednio kontrolują reprezentację ciągu wartości. Ciągi formatu przekazywane do metody wartości ToString wyliczenia określają, czy wartość jest wyświetlana przy użyciu nazwy ciągu (specyfikatorów formatu "G" i "F"), jego podstawowej wartości całkowitej (specyfikator formatu "D" lub jego wartości szesnastkowej (specyfikator formatu "X"). Poniższy przykład ilustruje użycie standardowych ciągów formatu do formatowania DayOfWeek wartości wyliczenia.

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
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

Aby uzyskać informacje na temat ciągów formatu wyliczenia, zobacz Ciągi formatu wyliczenia.

Standardowe ciągi formatu dla typów liczbowych zwykle definiują ciąg wynikowy, którego dokładny wygląd jest kontrolowany przez co najmniej jedną wartość właściwości. Na przykład specyfikator formatu "C" formatuje liczbę jako wartość waluty. Podczas wywoływania ToString metody z specyfikatorem formatu "C" jako jedynym parametrem są używane następujące wartości właściwości z obiektu bieżącej kultury NumberFormatInfo do zdefiniowania reprezentacji ciągu wartości liczbowej:

  • Właściwość CurrencySymbol , która określa symbol waluty bieżącej kultury.

  • Właściwość CurrencyNegativePattern or CurrencyPositivePattern , która zwraca liczbę całkowitą określającą następujące elementy:

    • Umieszczenie symbolu waluty.

    • Niezależnie od tego, czy wartości ujemne są wskazywane przez wiodący znak ujemny, znak końcowy ujemny lub nawiasy.

    • Czy odstęp pojawia się między wartością liczbową a symbolem waluty.

  • Właściwość CurrencyDecimalDigits , która definiuje liczbę cyfr ułamkowych w ciągu wynikowym.

  • Właściwość CurrencyDecimalSeparator , która definiuje symbol separatora dziesiętnego w ciągu wynikowym.

  • Właściwość CurrencyGroupSeparator , która definiuje symbol separatora grup.

  • Właściwość CurrencyGroupSizes , która definiuje liczbę cyfr w każdej grupie po lewej stronie dziesiętnej.

  • Właściwość NegativeSign , która określa znak ujemny używany w ciągu wyniku, jeśli nawiasy nie są używane do wskazywania wartości ujemnych.

Ponadto ciągi formatu liczbowego mogą zawierać specyfikator dokładności. Znaczenie tego specyfikatora zależy od ciągu formatu, z którym jest używany, ale zazwyczaj wskazuje całkowitą liczbę cyfr lub liczbę cyfr ułamkowych, które powinny pojawić się w ciągu wynikowym. Na przykład w poniższym przykładzie użyto standardowego ciągu liczbowego "X4" i specyfikatora dokładności do utworzenia wartości ciągu zawierającej cztery cyfry szesnastkowe.

byte[] byteValues = { 12, 163, 255 };
foreach (byte byteValue in byteValues)
   Console.WriteLine(byteValue.ToString("X4"));
// The example displays the following output:
//       000C
//       00A3
//       00FF
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

Aby uzyskać więcej informacji na temat standardowych ciągów formatowania liczbowego, zobacz Standardowe ciągi formatu liczbowego.

Standardowe ciągi formatu dla wartości daty i godziny to aliasy ciągów formatu niestandardowego przechowywane przez określoną DateTimeFormatInfo właściwość. Na przykład wywołanie ToString metody wartości daty i godziny z specyfikatorem formatu "D" wyświetla datę i godzinę przy użyciu niestandardowego ciągu formatu przechowywanego we właściwości bieżącej kultury DateTimeFormatInfo.LongDatePattern . (Aby uzyskać więcej informacji na temat ciągów formatu niestandardowego, zobacz następną sekcję). Poniższy przykład ilustruje tę relację.

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
Imports System.Globalization

Module Example
    Public Sub Main0()
        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

Aby uzyskać więcej informacji na temat standardowych ciągów formatu daty i godziny, zobacz Standardowe ciągi formatu daty i godziny.

Można również użyć standardowych ciągów formatu, aby zdefiniować reprezentację ciągu obiektu zdefiniowanego przez aplikację, który jest generowany przez metodę obiektu ToString(String) . Można zdefiniować określone standardowe specyfikatory formatu obsługiwane przez obiekt i określić, czy są one uwzględniane w wielkości liter, czy bez uwzględniania wielkości liter. Implementacja ToString(String) metody powinna obsługiwać następujące elementy:

  • Specyfikator formatu "G", który reprezentuje niestandardowy lub wspólny format obiektu. Przeciążenie bez parametrów metody obiektu ToString powinno wywołać jego ToString(String) przeciążenie i przekazać go do standardowego ciągu formatu "G".

  • Obsługa specyfikatora formatu, który jest równy odwołaniu o wartości null (Nothing w Visual Basic). Specyfikator formatu, który jest równy odwołaniu o wartości null, powinien być traktowany jako odpowiednik specyfikatora formatu "G".

Na przykład Temperature klasa może wewnętrznie przechowywać temperaturę w stopniach Celsjusza i używać specyfikatorów formatu do reprezentowania wartości Temperature obiektu w stopniach Celsjusza, stopniach Fahrenheita i kelvins. Poniższy przykład stanowi ilustrację.

using System;

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 "G":
         case "C":
            return this.Celsius.ToString("N2") + " °C";
         default:
            throw new FormatException(String.Format("The '{0}' format string is not supported.", format));
      }
   }
}

public class Example1
{
   public static void Main()
   {
      Temperature temp1 = new Temperature(0m);
      Console.WriteLine(temp1.ToString());
      Console.WriteLine(temp1.ToString("G"));
      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("G"));
      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("G"));
      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
//       0.00 °C
//       32.00 °F
//       273.15 K
//       -40.00 °C
//       -40.00 °C
//       -40.00 °C
//       -40.00 °F
//       233.15 K
//       16.00 °C
//       16.00 °C
//       16.00 °C
//       60.80 °F
//       289.15 K
//       The temperature is now 16.00 °C.
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()

        Select Case format
            Case "F"
                ' Convert temperature to Fahrenheit and return string.
                Return Me.Fahrenheit.ToString("N2") & " °F"
            Case "K"
                ' Convert temperature to Kelvin and return string.
                Return Me.Kelvin.ToString("N2") & " K"
            Case "C", "G"
                ' Return temperature in Celsius.
                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 Example1
    Public Sub Main1()
        Dim temp1 As New Temperature(0D)
        Console.WriteLine(temp1.ToString())
        Console.WriteLine(temp1.ToString("G"))
        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("G"))
        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("G"))
        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
'       0.00 °C
'       32.00 °F
'       273.15 K
'       -40.00 °C
'       -40.00 °C
'       -40.00 °C
'       -40.00 °F
'       233.15 K
'       16.00 °C
'       16.00 °C
'       16.00 °C
'       60.80 °F
'       289.15 K
'       The temperature is now 16.00 °C.

Niestandardowe ciągi formatowania

Oprócz standardowych ciągów formatu platforma .NET definiuje niestandardowe ciągi formatu zarówno dla wartości liczbowych, jak i wartości daty i godziny. Ciąg formatu niestandardowego składa się z co najmniej jednego specyfikatora formatu niestandardowego definiującego reprezentację ciągu wartości. Na przykład niestandardowy ciąg formatu daty i godziny "rrrr/mm/dd hh:mm:ss.ffff t zzz" konwertuje datę na reprezentację ciągu w postaci "2008/11/15 07:45:00.0000 P -08:000" dla kultury en-US. Podobnie ciąg formatu niestandardowego "0000" konwertuje wartość całkowitą 12 na "0012". Aby uzyskać pełną listę ciągów formatu niestandardowego, zobacz Niestandardowe ciągi formatu daty i godziny oraz niestandardowe ciągi formatu liczbowego.

Jeśli ciąg formatu składa się z pojedynczego specyfikatora formatu niestandardowego, specyfikator formatu powinien być poprzedzony symbolem procentu (%) w celu uniknięcia pomyłek ze specyfikatorem formatu standardowego. W poniższym przykładzie użyto specyfikatora formatu niestandardowego "M", aby wyświetlić jedną cyfrę lub dwie cyfry miesiąca określonej daty.

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

Wiele standardowych ciągów formatu dla wartości daty i godziny to aliasy ciągów formatu niestandardowego DateTimeFormatInfo , które są definiowane przez właściwości obiektu. Niestandardowe ciągi formatu oferują również znaczną elastyczność w zapewnianiu formatowania zdefiniowanego przez aplikację dla wartości liczbowych lub wartości daty i godziny. Możesz zdefiniować własne niestandardowe ciągi wyników dla wartości liczbowych i wartości daty i godziny, łącząc wiele specyfikatorów formatu niestandardowego w jeden niestandardowy ciąg formatu. Poniższy przykład definiuje niestandardowy ciąg formatu, który wyświetla dzień tygodnia w nawiasach po nazwie miesiąca, dniu i roku.

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)
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)      

W poniższym przykładzie zdefiniowano niestandardowy ciąg formatu, który wyświetla Int64 wartość jako standardową, siedmiocyfrową numer telefonu USA wraz z jego kodem obszaru.

using System;

public class Example17
{
   public static void Main()
   {
      long number = 8009999999;
      string fmt = "000-000-0000";
      Console.WriteLine(number.ToString(fmt));
   }
}
// The example displays the following output:
//        800-999-9999
Module Example18
    Public Sub Main18()
        Dim number As Long = 8009999999
        Dim fmt As String = "000-000-0000"
        Console.WriteLine(number.ToString(fmt))
    End Sub
End Module
' The example displays the following output:

' The example displays the following output:
'       800-999-9999

Chociaż standardowe ciągi formatu zwykle obsługują większość potrzeb formatowania dla typów zdefiniowanych przez aplikację, można również zdefiniować specyfikatory formatu niestandardowego w celu formatowania typów.

Formatowanie ciągów i typów platformy .NET

Wszystkie typy liczbowe (czyli Byte, , , DoubleDecimalInt32SByteInt16UInt32Int64SingleUInt64UInt16i BigInteger typy), a także DateTimeDateTimeOffsetTimeSpanGuidtypy , , i wszystkich typów wyliczenia, obsługują formatowanie za pomocą ciągów formatu. Aby uzyskać informacje na temat określonych ciągów formatu obsługiwanych przez każdy typ, zobacz następujące tematy:

Tytuł Definicja
Standardowe ciągi formatów liczbowych Opisuje standardowe ciągi formatu, które tworzą często używane reprezentacje ciągów wartości liczbowych.
Niestandardowe ciągi formatu liczbowego Opisuje niestandardowe ciągi formatu, które tworzą formaty specyficzne dla aplikacji dla wartości liczbowych.
Standardowe ciągi formatu daty i godziny Opisuje standardowe ciągi formatu, które tworzą często używane reprezentacje ciągów DateTime i DateTimeOffset wartości.
Niestandardowe ciągi formatu daty i godziny Opisuje niestandardowe ciągi formatu, które tworzą formaty specyficzne dla aplikacji dla DateTime wartości i DateTimeOffset .
Ciągi formatu Standard TimeSpan Opisuje standardowe ciągi formatu, które tworzą często używane reprezentacje ciągów interwałów czasu.
Niestandardowe ciągi formatu TimeSpan Opisuje niestandardowe ciągi formatu, które tworzą formaty specyficzne dla aplikacji dla interwałów czasowych.
Ciągi formatu wyliczenia Opisuje standardowe ciągi formatu używane do tworzenia reprezentacji ciągów wartości wyliczenia.
Guid.ToString(String) Opisuje standardowe ciągi formatu dla Guid wartości.

Formatowanie wrażliwe na kulturę za pomocą dostawców formatu

Chociaż specyfikatory formatu umożliwiają dostosowanie formatowania obiektów, tworzenie znaczącej reprezentacji ciągów obiektów często wymaga dodatkowych informacji o formatowaniu. Na przykład formatowanie liczby jako wartości waluty przy użyciu standardowego ciągu formatu "C" lub niestandardowego ciągu formatu, takiego jak "$ #,#.00" wymaga co najmniej informacji o prawidłowym symbolu waluty, separatorze grupy i separatorze dziesiętnym, który ma być dostępny do uwzględnienia w sformatowanym ciągu. Na platformie .NET te dodatkowe informacje dotyczące formatowania są udostępniane za pośrednictwem interfejsu IFormatProvider , który jest dostarczany jako parametr do co najmniej jednego przeciążenia ToString metody typów liczbowych i typów daty i godziny. IFormatProvider implementacje są używane na platformie .NET do obsługi formatowania specyficznego dla kultury. W poniższym przykładzie pokazano, jak reprezentacja ciągu obiektu zmienia się, gdy jest sformatowana z trzema IFormatProvider obiektami reprezentującymi różne kultury.

using System;
using System.Globalization;

public class Example18
{
   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 €
Imports System.Globalization

Public Module Example11
    Public Sub Main11()
        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 €

Interfejs IFormatProvider zawiera jedną metodę , GetFormat(Type)która ma pojedynczy parametr określający typ obiektu, który udostępnia informacje o formatowaniu. Jeśli metoda może podać obiekt tego typu, zwraca go. W przeciwnym razie zwraca odwołanie o wartości null (Nothing w Visual Basic).

IFormatProvider.GetFormat to metoda wywołania zwrotnego. Wywołanie ToString przeciążenia metody zawierającego IFormatProvider parametr wywołuje GetFormat metodę tego IFormatProvider obiektu. Metoda GetFormat jest odpowiedzialna za zwracanie obiektu, który dostarcza niezbędne informacje dotyczące formatowania, określone przez jego formatType parametr, do ToString metody .

Wiele metod formatowania lub konwersji ciągów zawiera parametr typu IFormatProvider, ale w wielu przypadkach wartość parametru jest ignorowana, gdy metoda jest wywoływana. W poniższej tabeli wymieniono niektóre metody formatowania, które używają parametru i typu Type obiektu przekazywanego IFormatProvider.GetFormat do metody.

Metoda Typ parametru formatType
ToString metoda typów liczbowych System.Globalization.NumberFormatInfo
ToString metoda typów daty i godziny System.Globalization.DateTimeFormatInfo
String.Format System.ICustomFormatter
StringBuilder.AppendFormat System.ICustomFormatter

Uwaga

ToString Metody typów liczbowych i typów daty i godziny są przeciążone, a tylko niektóre przeciążenia obejmują IFormatProvider parametr. Jeśli metoda nie ma parametru typu IFormatProvider, obiekt zwracany przez CultureInfo.CurrentCulture właściwość jest przekazywany zamiast tego. Na przykład wywołanie metody domyślnej Int32.ToString() ostatecznie powoduje wywołanie metody, takie jak: Int32.ToString("G", System.Globalization.CultureInfo.CurrentCulture).

Platforma .NET udostępnia trzy klasy, które implementują IFormatProvider:

Możesz również zaimplementować własnego dostawcę formatu, aby zastąpić dowolną z tych klas. Jednak metoda implementacji GetFormat musi zwrócić obiekt typu wymienionego w poprzedniej tabeli, jeśli musi dostarczyć informacje o formatowaniu do ToString metody.

Formatowanie wartości liczbowych uwzględniające kulturę

Domyślnie formatowanie wartości liczbowych jest wrażliwe na kulturę. Jeśli nie określisz kultury podczas wywoływania metody formatowania, są używane konwencje formatowania bieżącej kultury. Przedstawiono to w poniższym przykładzie, który zmienia bieżącą kulturę cztery razy, a następnie wywołuje metodę Decimal.ToString(String) . W każdym przypadku ciąg wynikowy odzwierciedla konwencje formatowania bieżącej kultury. Jest to spowodowane tym, że ToString metody i ToString(String) zawijają wywołania metody każdego typu liczbowego ToString(String, IFormatProvider) .

using System.Globalization;

public class Example6
{
   public static void Main()
   {
      string[] cultureNames = { "en-US", "fr-FR", "es-MX", "de-DE" };
      Decimal value = 1043.17m;

      foreach (var cultureName in cultureNames) {
         // Change the current culture.
         CultureInfo.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureName);
         Console.WriteLine($"The current culture is {CultureInfo.CurrentCulture.Name}");
         Console.WriteLine(value.ToString("C2"));
         Console.WriteLine();
      }
   }
}
// The example displays the following output:
//       The current culture is en-US
//       $1,043.17
//
//       The current culture is fr-FR
//       1 043,17 €
//
//       The current culture is es-MX
//       $1,043.17
//
//       The current culture is de-DE
//       1.043,17 €
Imports System.Globalization

Module Example6
    Public Sub Main6()
        Dim cultureNames() As String = {"en-US", "fr-FR", "es-MX", "de-DE"}
        Dim value As Decimal = 1043.17D

        For Each cultureName In cultureNames
            ' Change the current culture.
            CultureInfo.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureName)
            Console.WriteLine($"The current culture is {CultureInfo.CurrentCulture.Name}")
            Console.WriteLine(value.ToString("C2"))
            Console.WriteLine()
        Next
    End Sub
End Module
' The example displays the following output:
'       The current culture is en-US
'       $1,043.17
'       
'       The current culture is fr-FR
'       1 043,17 €
'       
'       The current culture is es-MX
'       $1,043.17
'       
'       The current culture is de-DE
'       1.043,17 €

Można również sformatować wartość liczbową dla określonej kultury, wywołując ToString przeciążenie, które ma provider parametr i przekazując jedną z następujących wartości:

W poniższym przykładzie użyto NumberFormatInfo obiektów reprezentujących kultury angielskie (Stany Zjednoczone) i angielskie (Zjednoczone Królestwo) oraz francuskie i rosyjskie neutralne kultury do formatowania liczby zmiennoprzecinkowych.

using System.Globalization;

public class Example7
{
    public static void Main()
    {
        double value = 1043.62957;
        string[] cultureNames = { "en-US", "en-GB", "ru", "fr" };

        foreach (string? name in cultureNames)
        {
            NumberFormatInfo nfi = CultureInfo.CreateSpecificCulture(name).NumberFormat;
            Console.WriteLine("{0,-6} {1}", name + ":", value.ToString("N3", nfi));
        }
    }
}
// The example displays the following output:
//       en-US: 1,043.630
//       en-GB: 1,043.630
//       ru:    1 043,630
//       fr:    1 043,630
Imports System.Globalization

Module Example7
    Public Sub Main7()
        Dim value As Double = 1043.62957
        Dim cultureNames() As String = {"en-US", "en-GB", "ru", "fr"}

        For Each name In cultureNames
            Dim nfi As NumberFormatInfo = CultureInfo.CreateSpecificCulture(name).NumberFormat
            Console.WriteLine("{0,-6} {1}", name + ":", value.ToString("N3", nfi))
        Next
    End Sub
End Module
' The example displays the following output:
'       en-US: 1,043.630
'       en-GB: 1,043.630
'       ru:    1 043,630
'       fr:    1 043,630

Formatowanie z uwzględnieniem kultury wartości daty i godziny

Domyślnie formatowanie wartości daty i godziny jest wrażliwe na kulturę. Jeśli nie określisz kultury podczas wywoływania metody formatowania, są używane konwencje formatowania bieżącej kultury. Przedstawiono to w poniższym przykładzie, który zmienia bieżącą kulturę cztery razy, a następnie wywołuje metodę DateTime.ToString(String) . W każdym przypadku ciąg wynikowy odzwierciedla konwencje formatowania bieżącej kultury. Wynika to z tego, że DateTime.ToString()metody , DateTime.ToString(String), DateTimeOffset.ToString()i DateTimeOffset.ToString(String) opakowuje wywołania metod DateTime.ToString(String, IFormatProvider) i DateTimeOffset.ToString(String, IFormatProvider) .

using System.Globalization;

public class Example4
{
   public static void Main()
   {
      string[] cultureNames = { "en-US", "fr-FR", "es-MX", "de-DE" };
      DateTime dateToFormat = new DateTime(2012, 5, 28, 11, 30, 0);

      foreach (var cultureName in cultureNames) {
         // Change the current culture.
         CultureInfo.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureName);
         Console.WriteLine($"The current culture is {CultureInfo.CurrentCulture.Name}");
         Console.WriteLine(dateToFormat.ToString("F"));
         Console.WriteLine();
      }
   }
}
// The example displays the following output:
//       The current culture is en-US
//       Monday, May 28, 2012 11:30:00 AM
//
//       The current culture is fr-FR
//       lundi 28 mai 2012 11:30:00
//
//       The current culture is es-MX
//       lunes, 28 de mayo de 2012 11:30:00 a.m.
//
//       The current culture is de-DE
//       Montag, 28. Mai 2012 11:30:00
Imports System.Globalization
Imports System.Threading

Module Example4
    Public Sub Main4()
        Dim cultureNames() As String = {"en-US", "fr-FR", "es-MX", "de-DE"}
        Dim dateToFormat As Date = #5/28/2012 11:30AM#

        For Each cultureName In cultureNames
            ' Change the current culture.
            CultureInfo.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureName)
            Console.WriteLine($"The current culture is {CultureInfo.CurrentCulture.Name}")
            Console.WriteLine(dateToFormat.ToString("F"))
            Console.WriteLine()
        Next
    End Sub
End Module
' The example displays the following output:
'       The current culture is en-US
'       Monday, May 28, 2012 11:30:00 AM
'       
'       The current culture is fr-FR
'       lundi 28 mai 2012 11:30:00
'       
'       The current culture is es-MX
'       lunes, 28 de mayo de 2012 11:30:00 a.m.
'       
'       The current culture is de-DE
'       Montag, 28. Mai 2012 11:30:00 

Można również sformatować wartość daty i godziny dla określonej kultury, wywołując DateTime.ToString przeciążenie lub DateTimeOffset.ToString , które ma provider parametr i przekazując jedną z następujących wartości:

W poniższym przykładzie użyto DateTimeFormatInfo obiektów reprezentujących kultury angielskie (Stany Zjednoczone) i angielski (Wielka Brytania) oraz kultury neutralne dla języka francuskiego i rosyjskiego, aby sformatować datę.

using System.Globalization;

public class Example5
{
   public static void Main()
   {
      DateTime dat1 = new(2012, 5, 28, 11, 30, 0);
      string[] cultureNames = { "en-US", "en-GB", "ru", "fr" };

      foreach (var name in cultureNames) {
         DateTimeFormatInfo dtfi = CultureInfo.CreateSpecificCulture(name).DateTimeFormat;
         Console.WriteLine($"{name}: {dat1.ToString(dtfi)}");
      }
   }
}
// The example displays the following output:
//       en-US: 5/28/2012 11:30:00 AM
//       en-GB: 28/05/2012 11:30:00
//       ru: 28.05.2012 11:30:00
//       fr: 28/05/2012 11:30:00
Imports System.Globalization

Module Example5
    Public Sub Main5()
        Dim dat1 As Date = #5/28/2012 11:30AM#
        Dim cultureNames() As String = {"en-US", "en-GB", "ru", "fr"}

        For Each name In cultureNames
            Dim dtfi As DateTimeFormatInfo = CultureInfo.CreateSpecificCulture(name).DateTimeFormat
            Console.WriteLine($"{name}: {dat1.ToString(dtfi)}")
        Next
    End Sub
End Module
' The example displays the following output:
'       en-US: 5/28/2012 11:30:00 AM
'       en-GB: 28/05/2012 11:30:00
'       ru: 28.05.2012 11:30:00
'       fr: 28/05/2012 11:30:00

Interfejs IFormattable

Zazwyczaj typy, które przeciążą metodę ToString ciągiem formatu, a IFormatProvider parametr implementuje IFormattable również interfejs. Ten interfejs ma jeden element członkowski, IFormattable.ToString(String, IFormatProvider)który zawiera zarówno ciąg formatu, jak i dostawcę formatu jako parametry.

Implementacja interfejsu IFormattable dla klasy zdefiniowanej przez aplikację ma dwie zalety:

W poniższym przykładzie zdefiniowano klasę Temperature , która implementuje IFormattable interfejs. Obsługuje specyfikatory formatu "C" lub "G", aby wyświetlić temperaturę w stopniach Celsjusza, specyfikator formatu "F" do wyświetlania temperatury w Fahrenheit i specyfikator formatu "K", aby wyświetlić temperaturę w Kelvin.

using System;
using System.Globalization;

namespace HotAndCold
{

    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 covert 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));
            }
        }
    }
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 '{format}' format string is not supported."))
        End Select
    End Function
End Class

Poniższy przykład tworzy wystąpienie Temperature obiektu. Następnie wywołuje metodę ToString i używa kilku ciągów formatu złożonego Temperature , aby uzyskać różne reprezentacje ciągów obiektu. Każda z tych metod wywołuje z kolei implementację IFormattableTemperature klasy .

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

Złożone formatowanie

Niektóre metody, takie jak String.Format i StringBuilder.AppendFormat, obsługują formatowanie złożone. Ciąg formatu złożonego jest rodzajem szablonu, który zwraca jeden ciąg, który zawiera reprezentację ciągu zero, co najmniej jeden obiekt. Każdy obiekt jest reprezentowany w ciągu formatu złożonego przez indeksowany element formatu. Indeks elementu formatu odpowiada pozycji obiektu, który reprezentuje na liście parametrów metody. Indeksy są oparte na zera. Na przykład w poniższym wywołaniu String.Format metody pierwszy element {0:D}formatu, , jest zastępowany przez reprezentację thatDateciągu ; drugi element {1}formatu , jest zastępowany przez reprezentację item1ciągu ; a trzeci element {2:C2}formatu, , jest zastępowany przez reprezentację item1.Valueciągu .

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.

Oprócz zamiany elementu formatu na reprezentację ciągu odpowiadającego mu obiektu elementy formatu umożliwiają również sterowanie następującymi elementami:

  • Konkretny sposób, w jaki obiekt jest reprezentowany jako ciąg, jeśli obiekt implementuje IFormattable interfejs i obsługuje ciągi formatu. Można to zrobić, postępując zgodnie z indeksem elementu formatu z dwukropkiem : , po którym następuje prawidłowy ciąg formatu. W poprzednim przykładzie za pomocą formatowania wartości daty z ciągiem formatu "d" (wzorzec daty krótkiej) (np {0:d}. ) i formatując wartość liczbową z ciągiem formatu "C2" (np {2:C2} . w celu reprezentowania liczby jako wartości walutowej z dwiema cyframi dziesiętnymi ułamkowymi).

  • Szerokość pola zawierającego reprezentację ciągu obiektu oraz wyrównanie reprezentacji ciągu w tym polu. Można to zrobić, postępując zgodnie z indeksem elementu formatu z przecinkiem , po szerokości pola. Ciąg jest wyrównany do prawej w polu, jeśli szerokość pola jest wartością dodatnią i jest wyrównana do lewej, jeśli szerokość pola jest wartością ujemną. Poniższy przykład wyrównuje wartości daty w polu daty 20 znaków i dopasowuje wartości dziesiętne do jednej cyfry ułamkowej w polu 11-znakowym.

    DateTime startDate = new DateTime(2015, 8, 28, 6, 0, 0);
    decimal[] temps = { 73.452m, 68.98m, 72.6m, 69.24563m,
                       74.1m, 72.156m, 72.228m };
    Console.WriteLine("{0,-20} {1,11}\n", "Date", "Temperature");
    for (int ctr = 0; ctr < temps.Length; ctr++)
       Console.WriteLine("{0,-20:g} {1,11:N1}", startDate.AddDays(ctr), temps[ctr]);
    
    // The example displays the following output:
    //       Date                 Temperature
    //
    //       8/28/2015 6:00 AM           73.5
    //       8/29/2015 6:00 AM           69.0
    //       8/30/2015 6:00 AM           72.6
    //       8/31/2015 6:00 AM           69.2
    //       9/1/2015 6:00 AM            74.1
    //       9/2/2015 6:00 AM            72.2
    //       9/3/2015 6:00 AM            72.2
    
    Dim startDate As New Date(2015, 8, 28, 6, 0, 0)
    Dim temps() As Decimal = {73.452, 68.98, 72.6, 69.24563,
                               74.1, 72.156, 72.228}
    Console.WriteLine("{0,-20} {1,11}", "Date", "Temperature")
    Console.WriteLine()
    For ctr As Integer = 0 To temps.Length - 1
        Console.WriteLine("{0,-20:g} {1,11:N1}", startDate.AddDays(ctr), temps(ctr))
    Next
    ' The example displays the following output:
    '       Date                 Temperature
    '
    '       8/28/2015 6:00 AM           73.5
    '       8/29/2015 6:00 AM           69.0
    '       8/30/2015 6:00 AM           72.6
    '       8/31/2015 6:00 AM           69.2
    '       9/1/2015 6:00 AM            74.1
    '       9/2/2015 6:00 AM            72.2
    '       9/3/2015 6:00 AM            72.2
    

    Należy pamiętać, że jeśli zarówno składnik ciągu wyrównania, jak i składnik ciągu formatu są obecne, poprzednie poprzedza ten ostatni (na przykład {0,-20:g}.

Aby uzyskać więcej informacji na temat formatowania złożonego, zobacz Formatowanie złożone.

Formatowanie niestandardowe za pomocą klasy ICustomFormatter

Dwie metody String.Format(IFormatProvider, String, Object[]) formatowania złożonego i StringBuilder.AppendFormat(IFormatProvider, String, Object[]), zawierają parametr dostawcy formatu, który obsługuje formatowanie niestandardowe. Po wywołaniu jednej z tych metod formatowania przekazuje Type obiekt reprezentujący ICustomFormatter interfejs do metody dostawcy GetFormat formatu. Metoda GetFormat jest następnie odpowiedzialna za zwrócenie implementacji ICustomFormatter , która zapewnia niestandardowe formatowanie.

Interfejs ICustomFormatter ma jedną metodę , Format(String, Object, IFormatProvider)która jest wywoływana automatycznie przez metodę formatowania złożonego, raz dla każdego elementu formatu w ciągu formatu złożonego. Metoda Format(String, Object, IFormatProvider) ma trzy parametry: ciąg formatu, który reprezentuje formatString argument w elemencie formatu, obiekt do sformatowania i IFormatProvider obiekt, który zapewnia usługi formatowania. Zazwyczaj klasa implementująca ICustomFormatter również implementuje IFormatProviderelement , więc ten ostatni parametr jest odwołaniem do niestandardowej klasy formatowania. Metoda zwraca niestandardową sformatowaną reprezentację ciągu obiektu do sformatowania. Jeśli metoda nie może sformatować obiektu, powinna zwrócić odwołanie o wartości null (Nothing w Visual Basic).

W poniższym przykładzie przedstawiono implementację ICustomFormatter o nazwie ByteByByteFormatter , która wyświetla wartości całkowite jako sekwencję dwucyfrowych wartości szesnastkowe, po których następuje spacja.

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();
   }
}
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

W poniższym przykładzie użyto ByteByByteFormatter klasy do formatowania wartości całkowitych. Należy pamiętać, że ICustomFormatter.Format metoda jest wywoływana więcej niż raz w drugim String.Format(IFormatProvider, String, Object[]) wywołaniu metody i że domyślny NumberFormatInfo dostawca jest używany w trzecim wywołaniu metody, ponieważ .ByteByByteFormatter.Format metoda nie rozpoznaje ciągu formatu "N0" i zwraca odwołanie o wartości null (Nothing w Visual Basic).

public class Example10
{
   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
Public Module Example10
    Public Sub Main10()
        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

Zobacz też

Tytuł Definicja
Standardowe ciągi formatów liczbowych Opisuje standardowe ciągi formatu, które tworzą powszechnie używane reprezentacje ciągów wartości liczbowych.
Niestandardowe ciągi formatu liczbowego Opisuje niestandardowe ciągi formatu, które tworzą formaty specyficzne dla aplikacji dla wartości liczbowych.
Standardowe ciągi formatu daty i godziny Opisuje standardowe ciągi formatu, które tworzą powszechnie używane reprezentacje ciągów DateTime wartości.
Niestandardowe ciągi formatu daty i godziny Opisuje niestandardowe ciągi formatu, które tworzą formaty specyficzne dla aplikacji dla DateTime wartości.
Standardowe ciągi formatu TimeSpan Opisuje standardowe ciągi formatu, które tworzą powszechnie używane reprezentacje ciągów interwałów czasu.
Niestandardowe ciągi formatu TimeSpan Opisuje niestandardowe ciągi formatu, które tworzą formaty specyficzne dla aplikacji dla interwałów czasu.
Ciągi formatu wyliczenia Opisuje standardowe ciągi formatu, które są używane do tworzenia reprezentacji ciągów wartości wyliczenia.
Formatowanie złożone Opisuje sposób osadzania co najmniej jednej sformatowanej wartości w ciągu. Ciąg może być następnie wyświetlany w konsoli programu lub zapisywany w strumieniu.
Analiza składniowa ciągów Opisuje sposób inicjowania obiektów do wartości opisanych przez reprezentacje ciągów tych obiektów. Analizowanie to odwrotna operacja formatowania.

Dokumentacja