NumberFormatInfo-Klasse

Dieser Artikel enthält ergänzende Hinweise zur Referenzdokumentation für diese API.

Die NumberFormatInfo-Klasse enthält kulturspezifische Informationen, die beim Formatieren und Analysieren numerischer Werte verwendet werden. Diese Informationen umfassen das Währungssymbol, das Dezimalsymbol, das Gruppentrennzeichen und die Symbole für positive und negative Vorzeichen.

Instanziieren eines NumberFormatInfo-Objekts

Sie können ein NumberFormatInfo-Objekt instanziieren, das die Formatierungskonventionen der aktuellen Kultur, der invarianten Kultur, einer spezifischen Kultur oder einer neutralen Kultur darstellt.

Instanziieren eines NumberFormatInfo-Objekts für die aktuelle Kultur

Sie können auf eine der folgenden Arten ein NumberFormatInfo-Objekt für die aktuelle Kultur instanziieren. In jedem Fall ist das zurückgegebene NumberFormatInfo-Objekt schreibgeschützt.

Im folgenden Beispiel werden diese drei Methoden zum Erstellen von NumberFormatInfo-Objekten verwendet, welche die Formatierungskonventionen der aktuellen Kultur darstellen. Außerdem wird der Wert der IsReadOnly-Eigenschaft abgerufen, um zu veranschaulichen, dass jedes Objekt schreibgeschützt ist.

using System;
using System.Globalization;

public class InstantiateEx1
{
    public static void Main()
    {
        NumberFormatInfo current1 = CultureInfo.CurrentCulture.NumberFormat;
        Console.WriteLine(current1.IsReadOnly);

        NumberFormatInfo current2 = NumberFormatInfo.CurrentInfo;
        Console.WriteLine(current2.IsReadOnly);

        NumberFormatInfo current3 = NumberFormatInfo.GetInstance(CultureInfo.CurrentCulture);
        Console.WriteLine(current3.IsReadOnly);
    }
}
// The example displays the following output:
//       True
//       True
//       True

Sie können ein beschreibbares NumberFormatInfo-Objekt erstellen, das die Konventionen der aktuellen Kultur auf eine der folgenden Arten darstellt:

Das folgende Beispiel veranschaulicht diese beiden Methoden zum Instanziieren eines NumberFormatInfo-Objekts und zeigt den Wert seiner IsReadOnly-Eigenschaft an, um zu veranschaulichen, dass das Objekt nicht schreibgeschützt ist.

using System;
using System.Globalization;

public class InstantiateEx2
{
    public static void Main()
    {
        NumberFormatInfo current1 = NumberFormatInfo.CurrentInfo;
        current1 = (NumberFormatInfo)current1.Clone();
        Console.WriteLine(current1.IsReadOnly);

        CultureInfo culture2 = CultureInfo.CreateSpecificCulture(CultureInfo.CurrentCulture.Name);
        NumberFormatInfo current2 = culture2.NumberFormat;
        Console.WriteLine(current2.IsReadOnly);
    }
}
// The example displays the following output:
//       False
//       False

Beachten Sie, dass das Windows-Betriebssystem es Benutzer*innen ermöglicht, einige der NumberFormatInfo-Eigenschaftswerte zu überschreiben, die in numerischen Formatierungs- und Analysevorgängen über das Element Region und Sprache in der Systemsteuerung verwendet werden. Beispielsweise können Benutzer*innen, deren Kultur „Englisch (USA)“ ist, Währungswerte im Format „1,1 USD“ statt im Standardformat „$1.1“ anzeigen. Die NumberFormatInfo-Objekte, die wie zuvor beschrieben abgerufen wurden, spiegeln diese benutzerdefinierten Außerkraftsetzungen wider. Wenn dies nicht erwünscht ist, können Sie ein NumberFormatInfo-Objekt erstellen, das keine benutzerdefinierte Außerkraftsetzungen widerspiegelt (und das auch Lese-/Schreibvorgänge zulässt statt schreibgeschützt zu sein), indem Sie den CultureInfo.CultureInfo(String, Boolean)-Konstruktor aufrufen und einen false-Wert für das useUserOverride-Argument angeben. Das folgende Beispiel veranschaulicht ein System, dessen aktuelle Kultur „Englisch (USA)“ ist und dessen Währungssymbol vom Standardwert „$“ in „USD“ geändert wurde.

using System;
using System.Globalization;

public class InstantiateEx3
{
    public static void Main()
    {
        CultureInfo culture;
        NumberFormatInfo nfi;

        culture = CultureInfo.CurrentCulture;
        nfi = culture.NumberFormat;
        Console.WriteLine("Culture Name:    {0}", culture.Name);
        Console.WriteLine("User Overrides:  {0}", culture.UseUserOverride);
        Console.WriteLine("Currency Symbol: {0}\n", culture.NumberFormat.CurrencySymbol);

        culture = new CultureInfo(CultureInfo.CurrentCulture.Name, false);
        Console.WriteLine("Culture Name:    {0}", culture.Name);
        Console.WriteLine("User Overrides:  {0}", culture.UseUserOverride);
        Console.WriteLine("Currency Symbol: {0}", culture.NumberFormat.CurrencySymbol);
    }
}
// The example displays the following output:
//       Culture Name:    en-US
//       User Overrides:  True
//       Currency Symbol: USD
//
//       Culture Name:    en-US
//       User Overrides:  False
//       Currency Symbol: $

Wenn die CultureInfo.UseUserOverride-Eigenschaft auf true festgelegt ist, werden auch die Eigenschaften CultureInfo.DateTimeFormat, CultureInfo.NumberFormat und CultureInfo.TextInfo aus den Benutzereinstellungen abgerufen. Wenn die Benutzereinstellungen nicht mit der Kultur kompatibel sind, die dem CultureInfo-Objekt zugeordnet ist (z. B. wenn der ausgewählte Kalender nicht einer der in der OptionalCalendars-Eigenschaft aufgelisteten Kalender ist), sind die Ergebnisse der Methoden und die Werte der Eigenschaften nicht definiert.

Instanziieren eines NumberFormatInfo-Objekts für die invariante Kultur

Die invariante Kultur stellt eine Kultur dar, die kulturunabhängig ist. Sie basiert auf der Sprache „Englisch“, doch nicht auf einem bestimmten englischsprachigen Land bzw. einer bestimmten englischsprachigen Region. Obwohl die Daten spezifischer Kulturen dynamisch sein und sich ändern können, um neue kulturelle Konventionen oder Benutzerpräferenzen widerzuspiegeln, ändern sich die Daten der invarianten Kultur nicht. Ein NumberFormatInfo-Objekt, das die Formatierungskonventionen der invarianten Kultur darstellt, kann für Formatierungsvorgänge verwendet werden, bei denen die Ergebniszeichenfolgen nicht je nach Kultur variieren sollten.

Sie können ein NumberFormatInfo-Objekt, das die Formatierungskonventionen der invarianten Kultur darstellt, wie folgt instanziieren:

Im folgenden Beispiel wird jede dieser Methoden verwendet, um ein NumberFormatInfo-Objekt zu instanziieren, das die invariante Kultur darstellt. Anschließend wird angegeben, ob das Objekt schreibgeschützt ist.

using System;
using System.Globalization;

public class InstantiateEx4
{
    public static void Main()
    {
        NumberFormatInfo nfi;

        nfi = System.Globalization.NumberFormatInfo.InvariantInfo;
        Console.WriteLine(nfi.IsReadOnly);

        nfi = CultureInfo.InvariantCulture.NumberFormat;
        Console.WriteLine(nfi.IsReadOnly);

        nfi = new NumberFormatInfo();
        Console.WriteLine(nfi.IsReadOnly);
    }
}
// The example displays the following output:
//       True
//       True
//       False

Instanziieren eines NumberFormatInfo-Objekts für eine spezifische Kultur

Eine spezifische Kultur stellt eine Sprache dar, die in einem bestimmten Land bzw. einer bestimmten Region gesprochen wird. Beispielsweise steht „en-US“ für eine spezifische Kultur, die die in den USA gesprochene englische Sprache darstellt. „en-CA“ ist eine spezifische Kultur, die die in Kanada gesprochene englische Sprache darstellt. Sie können ein NumberFormatInfo-Objekt, das die Formatierungskonventionen einer spezifischen Kultur darstellt, wie folgt instanziieren:

Im folgenden Beispiel werden diese vier Methoden verwendet, um ein NumberFormatInfo-Objekt zu erstellen, das die Formatierungskonventionen der indonesischen Kultur (Indonesien) widerspiegelt. Außerdem wird angegeben, ob jedes dieser Objekte schreibgeschützt ist.

using System;
using System.Globalization;

public class InstantiateEx5
{
    public static void Main()
    {
        CultureInfo culture;
        NumberFormatInfo nfi;

        nfi = CultureInfo.GetCultureInfo("id-ID").NumberFormat;
        Console.WriteLine("Read-only: {0}", nfi.IsReadOnly);

        culture = new CultureInfo("id-ID");
        nfi = NumberFormatInfo.GetInstance(culture);
        Console.WriteLine("Read-only: {0}", nfi.IsReadOnly);

        culture = CultureInfo.CreateSpecificCulture("id-ID");
        nfi = culture.NumberFormat;
        Console.WriteLine("Read-only: {0}", nfi.IsReadOnly);

        culture = new CultureInfo("id-ID");
        nfi = culture.NumberFormat;
        Console.WriteLine("Read-only: {0}", nfi.IsReadOnly);
    }
}
// The example displays the following output:
//       Read-only: True
//       Read-only: False
//       Read-only: False
//       Read-only: False

Instanziieren eines NumberFormatInfo-Objekts für eine neutrale Kultur

Eine neutrale Kultur stellt eine Kultur oder Sprache dar, die unabhängig von einem Land bzw. einer Region ist. Es handelt sich in der Regel um das übergeordnete Element einer oder mehrerer bestimmter Kulturen. Beispielsweise ist „fr“ eine neutrale Kultur für die Sprache „Französisch“ und die übergeordnete Kultur der Kultur „fr-FR“. Sie können ein NumberFormatInfo-Objekt, das die Formatierungskonventionen einer neutralen Kultur darstellt, auf die gleiche Weise erstellen ein NumberFormatInfo-Objekt, das die Formatierungskonventionen einer spezifischen Kultur darstellt.

Da eine neutrale Kultur unabhängig von einem bestimmten Land bzw. einer bestimmten Region ist, fehlen ihr jedoch kulturspezifische Formatierungsinformationen. Statt das NumberFormatInfo-Objekt mit generischen Werten zu füllen, gibt .NET ein NumberFormatInfo-Objekt zurück, das die Formatierungskonventionen einer spezifischen Kultur widerspiegelt, die eine untergeordnete Kultur der neutralen Kultur ist. Beispielsweise spiegelt das NumberFormatInfo-Objekt für die neutrale Kultur „en“ die Formatierungskonventionen der Kultur „en-US“ wider, und das NumberFormatInfo-Objekt für die Kultur „fr“ spiegelt die Formatierungskonventionen der Kultur „fr-FR“ wider.

Sie können Code wie den folgenden verwenden, um zu bestimmen, welche Formatierungskonventionen einer spezifischen Kultur jede neutrale Kultur darstellt.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;

public class InstantiateEx6
{
    public static void Main()
    {
        // Get all the neutral cultures
        List<String> names = new List<String>();
        Array.ForEach(CultureInfo.GetCultures(CultureTypes.NeutralCultures),
                      culture => names.Add(culture.Name));
        names.Sort();
        foreach (var name in names)
        {
            // Ignore the invariant culture.
            if (name == "") continue;

            ListSimilarChildCultures(name);
        }
    }

    private static void ListSimilarChildCultures(string name)
    {
        // Create the neutral NumberFormatInfo object.
        NumberFormatInfo nfi = CultureInfo.GetCultureInfo(name).NumberFormat;
        // Retrieve all specific cultures of the neutral culture.
        CultureInfo[] cultures = Array.FindAll(CultureInfo.GetCultures(CultureTypes.SpecificCultures),
                                 culture => culture.Name.StartsWith(name + "-", StringComparison.OrdinalIgnoreCase));
        // Create an array of NumberFormatInfo properties
        PropertyInfo[] properties = typeof(NumberFormatInfo).GetProperties(BindingFlags.Instance | BindingFlags.Public);
        bool hasOneMatch = false;

        foreach (var ci in cultures)
        {
            bool match = true;
            // Get the NumberFormatInfo for a specific culture.
            NumberFormatInfo specificNfi = ci.NumberFormat;
            // Compare the property values of the two.
            foreach (var prop in properties)
            {
                // We're not interested in the value of IsReadOnly.
                if (prop.Name == "IsReadOnly") continue;

                // For arrays, iterate the individual elements to see if they are the same.
                if (prop.PropertyType.IsArray)
                {
                    IList nList = (IList)prop.GetValue(nfi, null);
                    IList sList = (IList)prop.GetValue(specificNfi, null);
                    if (nList.Count != sList.Count)
                    {
                        match = false;
                        break;
                    }

                    for (int ctr = 0; ctr < nList.Count; ctr++)
                    {
                        if (!nList[ctr].Equals(sList[ctr]))
                        {
                            match = false;
                            break;
                        }
                    }
                }
                else if (!prop.GetValue(specificNfi).Equals(prop.GetValue(nfi)))
                {
                    match = false;
                    break;
                }
            }
            if (match)
            {
                Console.WriteLine("NumberFormatInfo object for '{0}' matches '{1}'",
                                          name, ci.Name);
                hasOneMatch = true;
            }
        }
        if (!hasOneMatch)
            Console.WriteLine("NumberFormatInfo object for '{0}' --> No Match", name);

        Console.WriteLine();
    }
}

Dynamische Daten

Die kulturspezifischen Daten zum Formatieren von numerischen Werten, die von der NumberFormatInfo-Klasse bereitgestellt werden, sind wie die von der CultureInfo-Klasse bereitgestellten kulturspezifischen Daten dynamisch. Sie sollten keine Annahmen über die Stabilität von Werten für NumberFormatInfo-Objekte, die bestimmten CultureInfo-Objekten zugeordnet sind, treffen. Nur die Daten, die von der invarianten Kultur und dem zugeordneten NumberFormatInfo-Objekt bereitgestellt werden, sind stabil. Andere Daten können sich aus folgenden Gründen zwischen Anwendungssitzungen oder sogar innerhalb einer einzelnen Sitzung ändern:

  • Systemupdates: Kulturelle Vorlieben wie Währungssymbole oder Währungsformate ändern sich im Laufe der Zeit. In diesem Fall beinhaltet Windows Update Änderungen im Zusammenhang mit dem NumberFormatInfo-Eigenschaftswert für eine bestimmte Kultur.

  • Ersatzkulturen Die CultureAndRegionInfoBuilder-Klasse kann verwendet werden, um die Daten einer vorhandenen Kultur zu ersetzen.

  • Kaskadierende Änderungen an Eigenschaftswerten Einige kulturbezogenen Eigenschaften können sich zur Laufzeit ändern, was wiederum dazu führt, dass sich NumberFormatInfo-Daten ändern. Beispielsweise kann die aktuelle Kultur programmgesteuert oder durch eine Benutzeraktion geändert werden. In diesem Fall ändert sich das von der CurrentInfo-Eigenschaft zurückgegebene NumberFormatInfo-Objekt in ein Objekt, das der aktuellen Kultur zugeordnet ist.

  • Benutzereinstellungen Benutzer*innen Ihrer Anwendung können einige der mit der aktuellen Systemkultur verbundenen Werte über die Optionen für Region und Sprache in der Systemsteuerung außer Kraft setzen. Beispielsweise können Benutzer*innen ein anderes Währungssymbol oder ein anderes Dezimaltrennzeichen auswählen. Wenn die CultureInfo.UseUserOverride-Eigenschaft auf true (ihren Standardwert) festgelegt ist, werden die Eigenschaften des NumberFormatInfo-Objekts auch über die Benutzereinstellungen abgerufen.

Alle benutzerdefinierten Eigenschaften eines NumberFormatInfo-Objekts werden initialisiert, wenn das Objekt erstellt wird. Es besteht nach wie vor die Möglichkeit der Inkonsistenz, da weder die Objekterstellung noch der benutzerdefinierte Außerkraftsetzungsprozess atomar ist und die relevanten Werte während der Objekterstellung geändert werden können. Diese Inkonsistenzen sollten jedoch äußerst selten vorkommen.

Sie können steuern, ob benutzerdefinierte Außerkraftsetzungen in NumberFormatInfo-Objekten, die dieselbe Kultur wie die aktuelle Kultur darstellen, widergespiegelt werden. In der folgenden Tabelle sind die Methoden aufgeführt, mit denen ein NumberFormatInfo-Objekt abgerufen werden kann. Zudem wird in der Tabelle angegeben, ob das resultierende Objekt benutzerdefinierte Außerkraftsetzungen widerspiegelt.

Quelle des CultureInfo- und NumberFormatInfo-Objekts Spiegelt benutzerdefinierte Außerkraftsetzungen wider
CultureInfo.CurrentCulture.NumberFormat-Eigenschaft Ja
NumberFormatInfo.CurrentInfo-Eigenschaft Ja
CultureInfo.CreateSpecificCulture-Methode Ja
CultureInfo.GetCultureInfo-Methode Nein
CultureInfo(String)-Konstruktor Ja
CultureInfo.CultureInfo(String, Boolean)-Konstruktor Ist vom Wert des useUserOverride-Parameters abhängig

Bei Verwendung des NumberFormatInfo-Objekts in Clientanwendungen zum Formatieren und Analysieren von Benutzereingaben oder zum Anzeigen numerischer Daten sollten Sie benutzerdefinierte Außerkraftsetzungen beachten, es sei denn, es gibt einen zwingenden Grund dies nicht zu tun. Im Zusammenhang mit Serveranwendungen oder unbeaufsichtigten Anwendungen sollten Sie benutzerdefinierte Außerkraftsetzungen nicht beachten. Wenn Sie das NumberFormatInfo-Objekt jedoch explizit oder implizit zum Speichern von numerischen Daten in Zeichenfolgenform nutzen, sollten Sie entweder ein NumberFormatInfo-Objekt verwenden, das die Formatierungskonventionen der invarianten Kultur widerspiegelt, oder Sie sollten eine benutzerdefinierte numerische Formatzeichenfolge angeben, die Sie unabhängig von der Kultur verwenden.

IFormatProvider, NumberFormatInfo und numerische Formatierung

Ein NumberFormatInfo-Objekt wird implizit oder explizit in allen numerischen Formatierungsvorgängen verwendet. Dazu gehören Aufrufe der folgenden Methoden:

Bei allen numerischen Formatierungsvorgängen wird eine IFormatProvider-Implementierung verwendet. Die IFormatProvider-Schnittstelle enthält eine einzelne Methode namens GetFormat(Type). Es handelt sich um eine Rückrufmethode, der ein Type-Objekt übergeben wird, das den Typ darstellt, der zum Bereitstellen von Formatierungsinformationen erforderlich ist. Die Methode ist dafür zuständig, entweder eine Instanz dieses Typs oder null zurückzugeben, wenn sie keine Instanz des Typs bereitstellen kann. .NET stellt zwei IFormatProvider-Implementierungen zum Formatieren von Zahlen bereit:

Wenn einer Formatierungsmethode nicht explizit eine IFormatProvider-Implementierung zur Verfügung gestellt wird, wird ein CultureInfo-Objekt verwendet, das von der CultureInfo.CurrentCulture-Eigenschaft zurückgegeben wird, die die aktuelle Kultur darstellt.

Im folgenden Beispiel wird die Beziehung zwischen der IFormatProvider-Schnittstelle und der NumberFormatInfo-Klasse in Formatierungsvorgängen durch die Definition einer IFormatProvider-Implementierung veranschaulicht. Die GetFormat-Methode zeigt den Typnamen des vom Formatierungsvorgang angeforderten Objekts an. Wenn die Schnittstelle ein NumberFormatInfo-Objekt anfordert, stellt diese Methode das NumberFormatInfo-Objekt für die aktuelle Kultur bereit. Wie die Ausgabe des Beispiels zeigt, fordert die Decimal.ToString(IFormatProvider)-Methode von einem NumberFormatInfo-Objekt die Bereitstellung von Formatierungsinformationen an, während die String.Format(IFormatProvider, String, Object[])-Methode NumberFormatInfo- und DateTimeFormatInfo-Objekte sowie eine ICustomFormatter-Implementierung anfordert.

using System;
using System.Globalization;

public class CurrentCultureFormatProvider : IFormatProvider
{
    public Object GetFormat(Type formatType)
    {
        Console.WriteLine("Requesting an object of type {0}",
                          formatType.Name);
        if (formatType == typeof(NumberFormatInfo))
            return NumberFormatInfo.CurrentInfo;
        else if (formatType == typeof(DateTimeFormatInfo))
            return DateTimeFormatInfo.CurrentInfo;
        else
            return null;
    }
}

public class FormatProviderEx
{
    public static void Main()
    {
        Decimal amount = 1203.541m;
        string value = amount.ToString("C2", new CurrentCultureFormatProvider());
        Console.WriteLine(value);
        Console.WriteLine();
        string composite = String.Format(new CurrentCultureFormatProvider(),
                                         "Date: {0}   Amount: {1}   Description: {2}",
                                         DateTime.Now, 1264.03m, "Service Charge");
        Console.WriteLine(composite);
        Console.WriteLine();
    }
}
// The example displays output like the following:
//    Requesting an object of type NumberFormatInfo
//    $1,203.54
//
//    Requesting an object of type ICustomFormatter
//    Requesting an object of type DateTimeFormatInfo
//    Requesting an object of type NumberFormatInfo
//    Date: 11/15/2012 2:00:01 PM   Amount: 1264.03   Description: Service Charge

Wenn nicht explizit eine IFormatProvider-Implementierung in einem Aufruf einer numerischen Formatierungsmethode bereitgestellt wird, ruft die Methode die CultureInfo.CurrentCulture.GetFormat-Methode auf, die das NumberFormatInfo-Objekt zurückgibt, das der aktuellen Kultur entspricht.

Formatzeichenfolgen und NumberFormatInfo-Eigenschaften

Jeder Formatierungsvorgang verwendet entweder eine standardmäßige oder eine benutzerdefinierte numerische Formatzeichenfolge, um eine Ergebniszeichenfolge aus einer Zahl zu erzeugen. In einigen Fällen wird explizit eine Formatzeichenfolge zum Erzeugen einer Ergebniszeichenfolge verwendet, wie im folgenden Beispiel gezeigt. In diesem Code wird die Decimal.ToString(IFormatProvider)-Methode aufgerufen, um einen Decimal-Wert mithilfe der Formatierungskonventionen der Kultur „en-US“ in eine Reihe verschiedener Zeichenfolgendarstellungen zu konvertieren.

using System;
using System.Globalization;

public class PropertiesEx1
{
    public static void Main()
    {
        string[] formatStrings = { "C2", "E1", "F", "G3", "N",
                                 "#,##0.000", "0,000,000,000.0##" };
        CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
        Decimal[] values = { 1345.6538m, 1921651.16m };

        foreach (var value in values)
        {
            foreach (var formatString in formatStrings)
            {
                string resultString = value.ToString(formatString, culture);
                Console.WriteLine("{0,-18} -->  {1}", formatString, resultString);
            }
            Console.WriteLine();
        }
    }
}
// The example displays the following output:
//       C2                 -->  $1,345.65
//       E1                 -->  1.3E+003
//       F                  -->  1345.65
//       G3                 -->  1.35E+03
//       N                  -->  1,345.65
//       #,##0.000          -->  1,345.654
//       0,000,000,000.0##  -->  0,000,001,345.654
//
//       C2                 -->  $1,921,651.16
//       E1                 -->  1.9E+006
//       F                  -->  1921651.16
//       G3                 -->  1.92E+06
//       N                  -->  1,921,651.16
//       #,##0.000          -->  1,921,651.160
//       0,000,000,000.0##  -->  0,001,921,651.16

In anderen Fällen ist die Verwendung einer Formatzeichenfolge implizit. Bei den folgenden Methodenaufrufen der Standard- oder parameterlosen Decimal.ToString()-Methode wird beispielsweise der Wert der Decimal-Instanz mithilfe des allgemeinen Formatspezifizierers („G“) und der Konventionen der aktuellen Kultur formatiert, die in diesem Fall die Kultur „en-US“ ist.

using System;

public class PropertiesEx2
{
    public static void Main()
    {
        Decimal[] values = { 1345.6538m, 1921651.16m };

        foreach (var value in values)
        {
            string resultString = value.ToString();
            Console.WriteLine(resultString);
            Console.WriteLine();
        }
    }
}
// The example displays the following output:
//       1345.6538
//
//       1921651.16

Jede numerische Standardformatzeichenfolge verwendet eine oder mehrereNumberFormatInfo-Eigenschaften, um das Muster oder die Symbole zu bestimmen, die in der Ergebniszeichenfolge verwendet werden. Entsprechend fügen alle benutzerdefinierten Zahlenformatspezifizierer außer „0“ und „#“ die durch NumberFormatInfo-Eigenschaften definierten Symbole in die Ergebniszeichenfolge ein. In der folgenden Tabelle sind die Standardformatspezifizierer und benutzerdefinierten Formatspezifizierer für Zahlen sowie die zugehörigen NumberFormatInfo-Eigenschaften aufgeführt. Informationen zum Ändern der Darstellung der Ergebniszeichenfolge für eine bestimmte Kultur finden Sie im Abschnitt Ändern der NumberFormatInfo-Eigenschaften. Ausführliche Informationen zur Verwendung dieser Formatspezifizierer finden Sie unter Standardformatzeichenfolgen für numerische Daten und Benutzerdefinierte numerische Formatzeichenfolgen.

Formatbezeichner Zugeordnete Eigenschaften
„C“ oder „c“ (Spezifizierer für das Währungsformat) CurrencyDecimalDigits zur Definition der Standardanzahl von Dezimalstellen.

CurrencyDecimalSeparator zur Definition des Dezimaltrennzeichens.

CurrencyGroupSeparator zur Definition des Gruppen- oder Tausendertrennzeichens.

CurrencyGroupSizes zur Definition der Größen von ganzzahligen Gruppen.

CurrencyNegativePattern zur Definition des Musters negativer Währungswerte.

CurrencyPositivePattern zur Definition des Musters positiver Währungswerte.

CurrencySymbol zur Definition des Währungssymbols.

NegativeSign zur Definition des Symbols für das negative Vorzeichen.
„D“ oder „d“ (Spezifizierer für das Dezimalformat) NegativeSign zur Definition des Symbols für das negative Vorzeichen.
„E“ oder „e“ (Spezifizierer für das exponentielle oder wissenschaftlicher Format) NegativeSign zur Definition des Symbols für das negative Vorzeichen in der Mantisse und im Exponenten.

NumberDecimalSeparator zur Definition des Dezimaltrennzeichens.

PositiveSign zur Definition des Symbols für das positive Vorzeichen in der Mantisse und im Exponenten.
„F“ oder „f“ (Spezifizierer für Festkommaformat) NegativeSign zur Definition des Symbols für das negative Vorzeichen.

NumberDecimalDigits zur Definition der Standardanzahl von Dezimalstellen.

NumberDecimalSeparator zur Definition des Dezimaltrennzeichens.
„G“ oder „g“ (Spezifizierer für das allgemeine Format) NegativeSign zur Definition des Symbols für das negative Vorzeichen.

NumberDecimalSeparator zur Definition des Dezimaltrennzeichens.

PositiveSign zur Definition des Symbols für das positive Vorzeichen für Ergebniszeichenfolgen im exponentiellen Format.
„N“ oder „n“ (Spezifizierer für das numerische Format) NegativeSign zur Definition des Symbols für das negative Vorzeichen.

NumberDecimalDigits zur Definition der Standardanzahl von Dezimalstellen.

NumberDecimalSeparator zur Definition des Dezimaltrennzeichens.

NumberGroupSeparator zur Definition des Gruppentrennzeichens (Tausender).

NumberGroupSizes zur Definition der ganzzahligen Ziffern in einer Gruppe.

NumberNegativePattern zur Definition des Formats negativer Werte.
„P“ oder „p“ (Spezifizierer für das Prozentformat) NegativeSign zur Definition des Symbols für das negative Vorzeichen.

PercentDecimalDigits zur Definition der Standardanzahl von Dezimalstellen.

PercentDecimalSeparator zur Definition des Dezimaltrennzeichens.

PercentGroupSeparator zur Definition des Gruppentrennzeichens.

PercentGroupSizes zur Definition der ganzzahligen Ziffern in einer Gruppe.

PercentNegativePattern zur Definition der Platzierung des Prozentsymbols sowie des Minuszeichens für negative Werte.

PercentPositivePattern zur Definition der Platzierung des Prozentsymbols für positive Werte.

PercentSymbol zur Definition des Prozentsymbols.
„R“ oder „r“ (Spezifizierer für das Roundtripformat) NegativeSign zur Definition des Symbols für das negative Vorzeichen.

NumberDecimalSeparator zur Definition des Dezimaltrennzeichens.

PositiveSign zur Definition des Symbols für das positive Vorzeichen in einem Exponenten.
„H“ oder „h“ (Spezifizierer für das Hexadezimalformat) Keine.
„.“ (benutzerdefinierter Spezifizierer für das Dezimaltrennzeichen) NumberDecimalSeparator zur Definition des Dezimaltrennzeichens.
„,“ (benutzerdefinierter Spezifizierer für das Gruppentrennzeichen) NumberGroupSeparator zur Definition des Symbols für das Gruppen- (oder Tausender)trennzeichen.
„%“ (benutzerdefinierter Spezifizierer für den Prozentplatzhalter) PercentSymbol zur Definition des Prozentsymbols.
„‰“ (benutzerdefinierter Spezifizierer für den Tausenderplatzhalter) PerMilleSymbol zur Definition des Symbols für das Tausendertrennzeichen.
„E“ (benutzerdefinierter Spezifizierer für die Exponentialschreibweise) NegativeSign zur Definition des Symbols für das negative Vorzeichen in der Mantisse und im Exponenten.

PositiveSign zur Definition des Symbols für das positive Vorzeichen in der Mantisse und im Exponenten.

Beachten Sie, dass die NumberFormatInfo-Klasse die NativeDigits-Eigenschaft enthält, die die Ziffern des Zahlensystems zur Basis 10 angibt, die von einer bestimmten Kultur verwendet werden. Die Eigenschaft wird jedoch nicht in Formatierungsvorgängen verwendet. Nur die einfachen lateinischen Ziffern 0 (U+0030) bis 9 (U+0039) werden in der Ergebniszeichenfolge verwendet. Darüber hinaus besteht die Ergebniszeichenfolge für Single- und Double-Werte von NaN, PositiveInfinity und NegativeInfinity aus den Symbolen, die durch die Eigenschaften NaNSymbol, PositiveInfinitySymbol bzw NegativeInfinitySymbol definiert sind.

Ändern der NumberFormatInfo-Eigenschaften

Sie können die Eigenschaften eines NumberFormatInfo-Objekts ändern, um die in einem numerischen Formatierungsvorgang erzeugte Ergebniszeichenfolge anzupassen. Gehen Sie hierzu folgendermaßen vor:

  1. Erstellen Sie eine lesbare und beschreibbare Kopie eines NumberFormatInfo-Objekts, dessen Formatierungskonventionen Sie ändern möchten. Weitere Informationen finden Sie im Abschnitt Instanziieren eines NumberFormatInfo-Objekts.

  2. Ändern Sie die Eigenschaft oder Eigenschaften, die verwendet werden, um die gewünschte Ergebniszeichenfolge zu generieren. Informationen dazu, wie Formatierungsmethoden NumberFormatInfo-Eigenschaften zum Definieren von Ergebniszeichenfolgen verwenden, finden Sie im Abschnitt Formatzeichenfolgen und NumberFormatInfo-Eigenschaften.

  3. Verwenden Sie das benutzerdefinierte NumberFormatInfo-Objekt als IFormatProvider-Argument in Aufrufen von Formatierungsmethoden.

Hinweis

Anstatt die Eigenschaftswerte einer Kultur bei jedem Start einer Anwendung dynamisch zu ändern, können Sie die CultureAndRegionInfoBuilder Klasse verwenden, um entweder eine benutzerdefinierte Kultur (eine Kultur mit einem eindeutigen Namen, die die vorhandene Kulturen ergänzt) oder eine Ersetzungskultur (eine Kultur, die anstelle einer bestimmten Kultur verwendet wird) zu definieren.

Die folgenden Abschnitte enthalten hierzu einige Beispiele.

Ändern des Währungssymbols und -musters

Im folgenden Beispiel wird ein NumberFormatInfo-Objekt geändert, das die Formatierungskonventionen der Kultur „en-US“ darstellt. Es weist der CurrencySymbol-Eigenschaft das ISO-4217-Währungssymbol zu und definiert ein Muster für Währungswerte, das aus dem Währungssymbol gefolgt von einem Leerzeichen und einem numerischen Wert besteht.

using System;
using System.Globalization;

public class Example
{
    public static void Main()
    {
        // Retrieve a writable NumberFormatInfo object.
        CultureInfo enUS = CultureInfo.CreateSpecificCulture("en-US");
        NumberFormatInfo nfi = enUS.NumberFormat;

        // Use the ISO currency symbol instead of the native currency symbol.
        nfi.CurrencySymbol = (new RegionInfo(enUS.Name)).ISOCurrencySymbol;
        // Change the positive currency pattern to <code><space><value>.
        nfi.CurrencyPositivePattern = 2;
        // Change the negative currency pattern to <code><space><sign><value>.
        nfi.CurrencyNegativePattern = 12;

        // Produce the result strings by calling ToString.
        Decimal[] values = { 1065.23m, 19.89m, -.03m, -175902.32m };
        foreach (var value in values)
            Console.WriteLine(value.ToString("C", enUS));

        Console.WriteLine();

        // Produce the result strings by calling a composite formatting method.
        foreach (var value in values)
            Console.WriteLine(String.Format(enUS, "{0:C}", value));
    }
}
// The example displays the following output:
//       USD 1,065.23
//       USD 19.89
//       USD -0.03
//       USD -175,902.32
//
//       USD 1,065.23
//       USD 19.89
//       USD -0.03
//       USD -175,902.32

Formatieren einer nationalen Identifikationsnummer

Viele nationale Identifikationsnummern bestehen ausschließlich aus Ziffern und können daher einfach durch die Änderung der Eigenschaften eines NumberFormatInfo-Objekts formatiert werden. Eine Sozialversicherungsnummer in den USA besteht z. B. aus 9 Ziffern, die wie folgt angeordnet sind: XXX-XX-XXXX. Das folgende Beispiel geht davon aus, dass Sozialversicherungsnummern als ganzzahlige Werte gespeichert werden, und formatiert sie entsprechend.

using System;
using System.Globalization;

public class CustomizeSSNEx
{
    public static void Main()
    {
        // Instantiate a read-only NumberFormatInfo object.
        CultureInfo enUS = CultureInfo.CreateSpecificCulture("en-US");
        NumberFormatInfo nfi = enUS.NumberFormat;

        // Modify the relevant properties.
        nfi.NumberGroupSeparator = "-";
        nfi.NumberGroupSizes = new int[] { 3, 2, 4 };
        nfi.NumberDecimalDigits = 0;

        int[] ids = { 111223333, 999776666 };

        // Produce the result string by calling ToString.
        foreach (var id in ids)
            Console.WriteLine(id.ToString("N", enUS));

        Console.WriteLine();

        // Produce the result string using composite formatting.
        foreach (var id in ids)
            Console.WriteLine(String.Format(enUS, "{0:N}", id));
    }
}
// The example displays the following output:
//       1112-23-333
//       9997-76-666
//
//       1112-23-333
//       9997-76-666

Analysieren numerischer Zeichenfolgen

Die Analyse umfasst das Konvertieren der Zeichenfolgendarstellung einer Zahl in eine Zahl. Jeder numerische Typ in .NET enthält zwei überladene Analysemethoden: Parse und TryParse. Die Parse-Methode konvertiert eine Zeichenfolge in eine Zahl und löst eine Ausnahme aus, wenn die Konvertierung fehlschlägt. Die TryParse-Methode konvertiert eine Zeichenfolge in eine Zahl, weist die Zahl einem out-Argument zu und gibt einen Boolean-Wert zurück, der angibt, ob die Konvertierung erfolgreich war.

Die Analysemethoden können implizit oder explizit einen NumberStyles-Enumerationswert verwenden, um zu bestimmen, welche Stilelemente (z. B. Gruppentrennzeichen, Dezimaltrennzeichen oder Währungssymbol) in einer Zeichenfolge vorhanden sein können, wenn der Analysevorgang erfolgreich ist. Wenn im NumberStyles-Methodenaufruf kein Wert angegeben wird, ist der Standardwert ein NumberStyles-Wert, der die Flags Float und AllowThousands enthält und angibt, dass die analysierte Zeichenfolge Gruppensymbole, ein Dezimaltrennzeichen, ein negatives Vorzeichen und Leerzeichen enthalten kann oder dass es sich um die Zeichenfolgendarstellung einer Zahl in exponentieller Schreibweise handeln kann.

Bei den Analysemethoden wird auch implizit oder explizit ein NumberFormatInfo-Objekt verwendet, das die spezifischen Symbole und Muster definiert, die in der zu analysierenden Zeichenfolge auftreten können. Wenn kein NumberFormatInfo-Objekt angegeben wird, ist der Standardwert das NumberFormatInfo für die aktuelle Kultur. Weitere Informationen zum Analysieren finden Sie in den Artikeln zu den einzelnen Analysemethoden, z. B. Int16.Parse(String), Int32.Parse(String, NumberStyles), Int64.Parse(String, IFormatProvider), Decimal.Parse(String, NumberStyles, IFormatProvider), Double.TryParse(String, Double) und BigInteger.TryParse(String, NumberStyles, IFormatProvider, BigInteger).

Im folgenden Beispiel wird die kulturabhängige Art der Analyse von Zeichenfolgen veranschaulicht. Es wird versucht, eine Zeichenfolge zu analysieren, die Tausendertrennzeichen enthält, indem die Konventionen der Kulturen „en-US“, „fr-FR“ und „invariant“ verwendet werden. Eine Zeichenfolge, die ein Komma als Gruppentrennzeichen und einen Punkt als Dezimaltrennzeichen enthält, kann in der Kultur „fr-FR“ nicht analysiert werden kann, und eine Zeichenfolge mit einem Leerzeichen als Gruppentrennzeichen und einem Komma als Dezimaltrennzeichen kann in den Kulturen „en-US“ und „invariant“ nicht analysiert werden.

using System;
using System.Globalization;

public class ParseEx1
{
    public static void Main()
    {
        String[] values = { "1,034,562.91", "9 532 978,07" };
        String[] cultureNames = { "en-US", "fr-FR", "" };

        foreach (var value in values)
        {
            foreach (var cultureName in cultureNames)
            {
                CultureInfo culture = CultureInfo.CreateSpecificCulture(cultureName);
                String name = culture.Name == "" ? "Invariant" : culture.Name;
                try
                {
                    Decimal amount = Decimal.Parse(value, culture);
                    Console.WriteLine("'{0}' --> {1} ({2})", value, amount, name);
                }
                catch (FormatException)
                {
                    Console.WriteLine("'{0}': FormatException ({1})",
                                      value, name);
                }
            }
            Console.WriteLine();
        }
    }
}
// The example displays the following output:
//       '1,034,562.91' --> 1034562.91 (en-US)
//       '1,034,562.91': FormatException (fr-FR)
//       '1,034,562.91' --> 1034562.91 (Invariant)
//
//       '9 532 978,07': FormatException (en-US)
//       '9 532 978,07' --> 9532978.07 (fr-FR)
//       '9 532 978,07': FormatException (Invariant)

Im Allgemeinen erfolgt das Analysieren in zwei Kontexten:

  • Als Vorgang, der zum Konvertieren von Benutzereingaben in einen numerischen Wert vorgesehen ist.

  • Als Vorgang, der als Roundtrip-Vorgang für einen numerischen Wert konzipiert ist; d. h., um einen numerischen Wert zu deserialisieren, der zuvor als Zeichenfolge serialisiert wurde.

In den folgenden Abschnitten werden diese beiden Vorgänge ausführlicher erläutert.

Analysieren von Benutzerzeichenfolgen

Wenn Sie von Benutzer*innen eingegebene numerische Zeichenfolgen analysieren, sollten Sie immer ein NumberFormatInfo-Objekt instanziieren, das jeweils die kulturellen Einstellungen der Benutzer*innen widerspiegelt. Informationen zum Instanziieren eines NumberFormatInfo-Objekts, das benutzerdefinierte kulturelle Anpassungen widerspiegelt, finden Sie im Abschnitt Dynamische Daten.

Das folgende Beispiel veranschaulicht den Unterschied zwischen einem Analysevorgang, der benutzerdefinierte kulturelle Einstellungen widerspiegelt, und einem Analysevorgang, der keine benutzerdefinierten kulturellen Einstellungen widerspiegelt. In diesem Fall ist die Standardsystemkultur „en-US“, aber der Benutzer bzw. die Benutzerin hat in der Systemsteuerung unter Region und Sprache „,“ als Dezimalsymbol und „.“ als Gruppentrennzeichen definiert. Normalerweise werden diese Symbole in der Kultur „en-US“ umgekehrt verwendet. Wenn die Benutzer*innen eine Zeichenfolge eingeben, die Benutzereinstellungen widerspiegelt, und die Zeichenfolge von einem NumberFormatInfo-Objekt, das ebenfalls Benutzereinstellungen (Außerkraftsetzungen) widerspiegelt, analysiert wird, gibt der Analysevorgang ein richtiges Ergebnis zurück. Wenn die Zeichenfolge jedoch von einem NumberFormatInfo-Objekt analysiert wird, das Standardeinstellungen für die Kultur „en-US“ widerspiegelt, ist das Kommasymbol als Gruppentrennzeichen falsch und gibt ein falsches Ergebnis zurück.

using System;
using System.Globalization;

public class ParseUserEx
{
    public static void Main()
    {
        CultureInfo stdCulture = CultureInfo.GetCultureInfo("en-US");
        CultureInfo custCulture = CultureInfo.CreateSpecificCulture("en-US");

        String value = "310,16";
        try
        {
            Console.WriteLine("{0} culture reflects user overrides: {1}",
                              stdCulture.Name, stdCulture.UseUserOverride);
            Decimal amount = Decimal.Parse(value, stdCulture);
            Console.WriteLine("'{0}' --> {1}", value, amount.ToString(CultureInfo.InvariantCulture));
        }
        catch (FormatException)
        {
            Console.WriteLine("Unable to parse '{0}'", value);
        }
        Console.WriteLine();

        try
        {
            Console.WriteLine("{0} culture reflects user overrides: {1}",
                              custCulture.Name, custCulture.UseUserOverride);
            Decimal amount = Decimal.Parse(value, custCulture);
            Console.WriteLine("'{0}' --> {1}", value, amount.ToString(CultureInfo.InvariantCulture));
        }
        catch (FormatException)
        {
            Console.WriteLine("Unable to parse '{0}'", value);
        }
    }
}
// The example displays the following output:
//       en-US culture reflects user overrides: False
//       '310,16' --> 31016
//
//       en-US culture reflects user overrides: True
//       '310,16' --> 310.16

Serialisieren und Deserialisieren von numerischen Daten

Wenn numerische Daten im Zeichenfolgenformat serialisiert und später deserialisiert und analysiert werden, sollten die Zeichenfolgen unter Verwendung der Konventionen der invarianten Kultur generiert und analysiert werden. Die Formatierungs- und Analysevorgänge sollten niemals die Konventionen einer spezifischen Kultur widerspiegeln. Wenn kulturspezifische Einstellungen verwendet werden, ist die Portabilität der Daten streng begrenzt. Sie können nur für einen Thread erfolgreich deserialisiert werden, dessen kulturspezifische Einstellungen mit denen des Threads identisch sind, für den sie serialisiert wurden. In einigen Fällen bedeutet dies, dass die Daten nicht einmal auf demselben System, auf dem sie serialisiert wurden, erfolgreich deserialisiert werden können.

Das folgende Beispiel veranschaulicht, was geschehen kann, wenn dieses Prinzip verletzt wird. Gleitkommawerte in einem Array werden in Zeichenfolgen konvertiert, wenn der aktuelle Thread die kulturspezifischen Einstellungen der Kultur „en-US“ verwendet. Die Daten werden dann von einem Thread analysiert, der die kulturspezifischen Einstellungen der Kultur „pt-BR“ verwendet. In diesem Fall ist zwar jeder Analysevorgang erfolgreich, die Daten werden jedoch nicht erfolgreich zurück konvertiert, sondern beschädigt. In anderen Fällen kann ein Analysevorgang fehlschlagen und eine FormatException-Ausnahme ausgelöst werden.

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Threading;

public class ParsePersistedEx
{
    public static void Main()
    {
        CultureInfo.CurrentCulture = CultureInfo.CreateSpecificCulture("en-US");
        PersistData();

        CultureInfo.CurrentCulture = CultureInfo.CreateSpecificCulture("pt-BR");
        RestoreData();
    }

    private static void PersistData()
    {
        // Define an array of floating-point values.
        Double[] values = { 160325.972, 8631.16, 1.304e5, 98017554.385,
                          8.5938287084321676e94 };
        Console.WriteLine("Original values: ");
        foreach (var value in values)
            Console.WriteLine(value.ToString("R", CultureInfo.InvariantCulture));

        // Serialize an array of doubles to a file
        StreamWriter sw = new StreamWriter(@".\NumericData.bin");
        for (int ctr = 0; ctr < values.Length; ctr++)
        {
            sw.Write(values[ctr].ToString("R"));
            if (ctr < values.Length - 1) sw.Write("|");
        }
        sw.Close();
        Console.WriteLine();
    }

    private static void RestoreData()
    {
        // Deserialize the data
        StreamReader sr = new StreamReader(@".\NumericData.bin");
        String data = sr.ReadToEnd();
        sr.Close();

        String[] stringValues = data.Split('|');
        List<Double> newValueList = new List<Double>();

        foreach (var stringValue in stringValues)
        {
            try
            {
                newValueList.Add(Double.Parse(stringValue));
            }
            catch (FormatException)
            {
                newValueList.Add(Double.NaN);
            }
        }

        Console.WriteLine("Restored values:");
        foreach (var newValue in newValueList)
            Console.WriteLine(newValue.ToString("R", NumberFormatInfo.InvariantInfo));
    }
}
// The example displays the following output:
//       Original values:
//       160325.972
//       8631.16
//       130400
//       98017554.385
//       8.5938287084321671E+94
//
//       Restored values:
//       160325972
//       863116
//       130400
//       98017554385
//       8.5938287084321666E+110