Kombinierte Formatierung

Die Funktion für die kombinierte Formatierung in .NET verwendet als Eingabe eine Liste von Objekten und eine kombinierte Formatzeichenfolge. Eine kombinierte Formatzeichenfolge besteht aus festgelegtem Text mit indizierten Platzhaltern, so genannten Formatelementen, die den Objekten in der Liste entsprechen. Der Formatierungsvorgang liefert eine Ergebniszeichenfolge, die sich aus dem ursprünglichen festgelegten Text und der Zeichenfolgendarstellung der Objekte in der Liste zusammensetzt.

Wichtig

Anstelle kombinierter Formatzeichenfolgen können Sie interpolierte Zeichenfolgen verwenden, wenn die von Ihnen verwendete Sprache und Sprachversion diese unterstützen. Eine interpolierte Zeichenfolge ist eine Zeichenfolge, die interpolierte Ausdrücke enthält. Jeder interpolierte Ausdruck wird mit dem Wert des Ausdrucks aufgelöst und in die Ergebniszeichenfolge aufgenommen, wenn die Zeichenfolge zugewiesen wird. Weitere Informationen finden Sie unter Zeichenfolgeninterpolation (C#-Referenz) und Interpolierte Zeichenfolgen (Visual Basic-Referenz).

Die Funktion für kombinierte Formatierung wird beispielsweise von folgenden Methoden unterstützt:

Kombinierte Formatzeichenfolge

Eine kombinierte Formatzeichenfolge und eine Objektliste dienen als Argumente von Methoden, die das Feature für die kombinierte Formatierung unterstützen. Die Quellzeichenfolge besteht aus 0 (null) oder mehreren Einheiten festgelegten Texts mit mindestens einem Formatelement. Der festgelegte Text ist eine von Ihnen ausgewählte beliebige Zeichenfolge. Jedes Formatelement entspricht einem Objekt oder einer geschachtelten Struktur in der Liste. Die Funktion für die kombinierte Formatierung gibt eine neue Ergebniszeichenfolge zurück, in der jedes Formatelement durch die Zeichenfolgendarstellung des entsprechenden Objekts in der Liste ersetzt wird.

Betrachten Sie das folgende Format-Codefragment:

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)

Der feste Text ist „Name =“ und „, hours =“. Die Formatelemente sind „{0}“ mit dem Index 0, was dem Objekt name entspricht, und „{1:hh}“ mit dem Index 1, was dem Objekt DateTime.Now entspricht.

Formatelementsyntax

Alle Formatelemente weisen die folgende Form auf und bestehen aus folgenden Komponenten:

{ Index[,Ausrichtung][:formatString]}

Die übereinstimmenden geschweiften Klammern ("{" and "}") sind erforderlich.

Indexkomponente

Bei der obligatorischen Komponente Index, dem so genannten Parameterbezeichner, handelt es sich um eine bei 0 (null) beginnende Zahl, mit der ein entsprechendes Element in der Objektliste angegeben wird. Das bedeutet, dass das Formatelement mit dem Parameterbezeichner 0 (null) das erste Objekt in der Liste formatiert, und das Formatelement mit dem Parameterbezeichner 1 formatiert das zweite Objekt in der Liste usw. Das folgende Beispiel enthält vier von null bis drei nummerierte Parameterbezeichner zur Darstellung von Primzahlen, die kleiner als zehn sind:

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

Mehrere Formatelemente können auf dasselbe Element in der Objektliste verweisen, indem derselbe Parameterbezeichner festgelegt wird. Sie können beispielsweise denselben numerischen Wert im hexadezimalen, im wissenschaftlichen und im Zahlenformat formatieren, indem Sie eine kombinierte Formatzeichenfolge wie die Folgende angeben: „0x{0:X} {0:E} {0:N}“ wie im folgenden Beispiel gezeigt.

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

Jedes Formatelement kann auf ein beliebiges Objekt in der Liste verweisen. Wenn beispielsweise drei Objekte vorliegen, können Sie das zweite, erste und dritte Objekt formatieren, indem Sie eine kombinierte Formatzeichenfolge wie die folgende angeben: „{1} {0} {2}“. Ein Objekt, auf das kein Formatelement verweist, wird ignoriert. Eine FormatException wird zur Laufzeit ausgelöst, wenn ein Parameterbezeichner auf ein Element außerhalb der Grenzen der Objektliste verweist.

Ausrichtungskomponente

Bei der optionalen Komponente Ausrichtung handelt es sich um eine ganze Zahl mit Vorzeichen, die die gewünschte formatierte Feldbreite angibt. Wenn der Wert für Ausrichtung kleiner als die Länge der formatierten Zeichenfolge ist, wird Ausrichtung ignoriert, und die Länge der formatierten Zeichenfolge wird als Feldbreite verwendet. Die formatierten Daten im Feld werden bei einem positiven Wert für Ausrichtung rechtsbündig und bei einem negativen Wert für Ausrichtung linksbündig ausgerichtet. Wenn Füllzeichen erforderlich sind, werden Leerräume verwendet. Das Komma ist erforderlich, wenn Ausrichtung angegeben wird.

Im folgenden Beispiel werden zwei Arrays definiert, ein Array mit den Namen der Mitarbeiter und ein Array mit den Arbeitsstunden der Mitarbeiter über einen Zeitraum von zwei Wochen. Die kombinierte Formatzeichenfolge richtet die Namen in einem Feld mit 20 Zeichen linksbündig aus, und die Stunden werden in einem Feld mit 5 Zeichen rechtsbündig ausgerichtet. Beachten Sie, dass auch die Standardformatzeichenfolge "N1" verwendet wird, um die Stunden mit einer Dezimalstelle zu formatieren.

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

Formatzeichenfolgen-Komponente

Die optionale Komponente Formatzeichenfolge ist eine Formatzeichenfolge, die für den formatierten Objekttyp geeignet ist. Geben Sie eine standardmäßige oder eine benutzerdefinierte numerische Formatzeichenfolge an, wenn das entsprechende Objekt ein numerischer Wert ist. Geben Sie eine standardmäßige oder eine benutzerdefinierte Formatzeichenfolge für Datum und Uhrzeit an, wenn das entsprechende Objekt ein DateTime-Objekt ist. Geben Sie eine Enumerationsformatzeichenfolge an, wenn das entsprechende Objekt ein Enumerationswert ist. Wenn Formatzeichenfolge nicht festgelegt ist, wird der allgemeine Formatbezeichner („G“) für einen numerischen, Datums- und Uhrzeit- oder Enumerationstyp verwendet. Der Doppelpunkt ist erforderlich, wenn Formatzeichenfolge angegeben wird.

Die folgende Tabelle listet Typen oder Kategorien von Typen in der .NET-Klassenbibliothek auf, die mehrere vordefinierte Formatzeichenfolgen unterstützen, und stellt Links zu Themen bereit, die diese unterstützten Formatzeichenfolgen auflisten. Beachten Sie, dass die Zeichenfolgenformatierung ein erweiterbarer Mechanismus ist, der es ermöglicht, neue Formatzeichenfolgen für alle vorhandenen Typen zu definieren und einen Satz von Formatzeichenfolgen zu definieren, der von einem anwendungsdefinierten Typ unterstützt wird. Weitere Informationen finden Sie unter den Themen zur IFormattable-Schnittstelle und ICustomFormatter-Schnittstelle.

Typ oder Typkategorie Siehe
Datums-/Zeittypen (DateTime, DateTimeOffset) Standard-Formatzeichenfolgen für Datum und Uhrzeit

Benutzerdefinierte Formatzeichenfolgen für Datum und Uhrzeit
Enumerationstypen (alle Typen abgeleitet von System.Enum) Enumerationsformatzeichenfolgen
Numerische Typen (BigInteger, Byte, Decimal, Double, Int16, Int32, Int64, SByte, Single, UInt16, UInt32, UInt64) Standardmäßige Zahlenformatzeichenfolgen

Benutzerdefinierte Zahlenformatzeichenfolgen
Guid Guid.ToString(String)
TimeSpan TimeSpan-Standardformatzeichenfolgen

Benutzerdefinierte TimeSpan-Formatzeichenfolgen

Versehen von geschweiften Klammern mit Escapezeichen

Öffnende und schließende geschweifte Klammern werden als Beginn und Ende eines Formatelements interpretiert. Deshalb müssen Sie eine Escapesequenz verwenden, um eine literale öffnende bzw. schließende geschweifte Klammer anzuzeigen. Geben Sie zwei öffnende geschweifte Klammern ("{{") im festgelegten Text an, um eine öffnende geschweifte Klammer ("{") anzuzeigen, und geben Sie entsprechend zwei schließende geschweifte Klammern ("}}") an, um eine schließende geschweifte Klammer ("}") anzuzeigen. Geschweifte Klammern in einem Formatelement werden sequenziell in der Reihenfolge interpretiert, in der sie angetroffen werden. Die Interpretation geschachtelter geschweifter Klammern wird nicht unterstützt.

Die Art und Weise, wie geschweifte Klammern mit Escapezeichen interpretiert werden, kann zu unerwarteten Ergebnissen führen. Betrachten Sie beispielsweise das Formatelement „{{{0:D}}}“, das eine öffnende geschweifte Klammer anzeigen soll, einen numerischen Wert, der als Dezimalzahl formatiert ist, und eine schließende geschweifte Klammer. Das Formatelement wird aber tatsächlich wie folgt interpretiert:

  1. Die ersten beiden öffnenden geschweiften Klammern ("{{") werden mit Escapezeichen versehen und ergeben eine öffnende geschweifte Klammer.

  2. Die nächsten drei Zeichen ("{0":) werden als Anfang eines Formatelements interpretiert.

  3. Das nächste Zeichen ("D") wird als Formatbezeichner für das numerische Standarddezimalformat interpretiert, und die nächsten beiden geschweiften Klammern mit Escapezeichen ergeben eine einzelne geschweifte Klammer. Da die entstehende Zeichenfolge ("D}") kein numerischer Standardformatbezeichner ist, wird sie als benutzerdefinierte Formatzeichenfolge interpretiert, d. h., es wird die Literalzeichenfolge "D}" angezeigt.

  4. Die letzte geschweifte Klammer ("}") wird als Ende des Formatelements interpretiert.

  5. Das Endergebnis, das angezeigt wird, ist die Literalzeichenfolge "{D}". Der numerische Wert, der formatiert werden sollte, wird nicht angezeigt.

Eine Möglichkeit, Code zu schreiben und dabei Probleme mit falsch interpretierten geschweiften Klammern und Formatelementen zu vermeiden, ist die separate Formatierung der geschweiften Klammern und Formatelemente. Zeigen Sie also beim ersten Formatierungsvorgang eine literale öffnende geschweifte Klammer, beim nächsten Formatierungsvorgang das Ergebnis des Formatelements und beim letzten Formatierungsvorgang eine literale schließende geschweifte Klammer an. Dieser Ansatz wird anhand des folgenden Beispiels veranschaulicht.

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}

Verarbeitungsreihenfolge

Wenn der Aufruf der Methode für die kombinierte Formatierung ein IFormatProvider-Argument enthält, dessen Wert nicht null ist, ruft die Laufzeit die IFormatProvider.GetFormat-Methode auf, um eine ICustomFormatter-Implementierung anzufordern. Wenn die Methode eine ICustomFormatter-Implementierung zurückgeben kann, wird diese während des gesamten Aufrufs der Methode zur kombinierten Formatierung zwischengespeichert.

Jeder Wert in der Parameterliste, der einem Formatelement entspricht, wird wie folgt in eine Zeichenfolge konvertiert:

  1. Wenn der zu formatierende Wert null ist, wird eine leere Zeichenfolge (String.Empty) zurückgegeben.

  2. Wenn eine ICustomFormatter-Implementierung verfügbar ist, ruft die Laufzeit die Format-Methode auf. Sie übergibt den formatString-Wert des Formatelements, sofern vorhanden, oder andernfalls null zusammen mit der IFormatProvider-Implementierung an die Methode. Wenn durch den Aufruf der ICustomFormatter.Format-Methode null zurückgegeben wird, wird der nächste Schritt ausgeführt. Andernfalls wird das Ergebnis des ICustomFormatter.Format-Aufrufs zurückgegeben.

  3. Wenn der Wert die IFormattable-Schnittstelle implementiert, wird die ToString(String, IFormatProvider)-Methode der Schnittstelle aufgerufen. Der Formatzeichenfolge-Wert wird, sofern im Formatelement vorhanden, an die Methode übergeben. Ist dies nicht der Fall, wird null übergeben. Das IFormatProvider-Argument wird wie folgt bestimmt:

    • Bei einem numerischen Wert fordert die Laufzeit im Fall, dass eine Methode zur kombinierten Formatierung mit einem IFormatProvider-Argument ungleich NULL aufgerufen wird, ein NumberFormatInfo-Objekt von ihrer IFormatProvider.GetFormat-Methode an. Wenn sie keines bereitstellen kann, wenn der Wert des Arguments null ist, oder wenn die Methode zur kombinierten Formatierung keinen IFormatProvider-Parameter hat, wird das NumberFormatInfo-Objekt für die aktuelle Threadkultur verwendet.

    • Bei einem Datums- und Uhrzeitwert fordert die Laufzeit im Fall, dass eine Methode zur kombinierten Formatierung mit einem IFormatProvider-Argument ungleich NULL aufgerufen wird, ein DateTimeFormatInfo-Objekt von ihrer IFormatProvider.GetFormat-Methode an. Wenn sie keines bereitstellen kann, wenn der Wert des Arguments null ist, oder wenn die Methode zur kombinierten Formatierung keinen IFormatProvider-Parameter hat, wird das DateTimeFormatInfo-Objekt für die aktuelle Threadkultur verwendet.

    • Bei Objekten anderer Typen wird beim Aufruf einer kombinierten Formatierungsmethode mit einem IFormatProvider-Argument der zugehörige Wert direkt an die IFormattable.ToString-Implementierung übergeben. Andernfalls wird null an die IFormattable.ToString-Implementierung übergeben.

  4. Die parameterlose ToString-Methode des Typs, die entweder Object.ToString() überschreibt oder das Verhalten ihrer Basisklasse erbt, wird aufgerufen. In diesem Fall wird die von der formatString-Komponente im Formatelement angegebene Formatzeichenfolge (sofern vorhanden) ignoriert.

Die Ausrichtung wird angewendet, nachdem die vorhergehenden Schritte durchgeführt wurden.

Codebeispiele

Das folgende Beispiel stellt eine Zeichenfolge dar, die mit der kombinierten Formatierung erstellt wurde, und eine weitere, die mit der ToString-Methode eines Objekts erstellt wurde. Beide Formatierungen führen zum gleichen Ergebnis.

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

Wenn das aktuelle Datum ein Donnerstag im Mai ist, lautet der Wert beider Zeichenfolgen im vorherigen Beispiel Thursday May in der Kultur Englisch (USA).

Console.WriteLine stellt die gleiche Funktionalität wie String.Format bereit. Der einzige Unterschied zwischen den beiden Methoden besteht darin, dass String.Format das Ergebnis als Zeichenfolge zurückgibt, während Console.WriteLine das Ergebnis in den Ausgabestrom schreibt, der dem Console-Objekt zugeordnet ist. Im folgenden Beispiel wird der Wert von Console.WriteLine mit der MyInt-Methode als Währungswert formatiert.

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

Das folgende Beispiel veranschaulicht die Formatierung mehrerer Objekte, wobei ein Objekt auf zwei Arten formatiert wird.

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                 

Das folgende Beispiel veranschaulicht die Verwendung der Ausrichtung beim Formatieren. Die zu formatierenden Argumente werden zwischen senkrechte Striche (|) platziert, um die resultierende Ausrichtung zu kennzeichnen.

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   |

Siehe auch