Klasa NumberFormatInfo

Ten artykuł zawiera dodatkowe uwagi dotyczące dokumentacji referencyjnej dla tego interfejsu API.

Klasa NumberFormatInfo zawiera informacje specyficzne dla kultury używane podczas formatowania i analizowania wartości liczbowych. Te informacje obejmują symbol waluty, symbol dziesiętny, symbol separatora grupy oraz symbole dla znaków dodatnich i ujemnych.

Tworzenie wystąpienia obiektu NumberFormatInfo

Można utworzyć wystąpienie NumberFormatInfo obiektu reprezentującego konwencje formatowania bieżącej kultury, niezmienną kulturę, określoną kulturę lub neutralną kulturę.

Utworzenie wystąpienia obiektu NumberFormatInfo dla bieżącej kultury

Możesz utworzyć wystąpienie NumberFormatInfo obiektu dla bieżącej kultury w dowolny z następujących sposobów. W każdym przypadku zwracany NumberFormatInfo obiekt jest tylko do odczytu.

W poniższym przykładzie użyto tych trzech sposobów tworzenia NumberFormatInfo obiektów reprezentujących konwencje formatowania bieżącej kultury. Pobiera również wartość właściwości, aby zilustrować IsReadOnly , że każdy obiekt jest tylko do odczytu.

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

Można utworzyć zapisywalny NumberFormatInfo obiekt reprezentujący konwencje bieżącej kultury w dowolny z następujących sposobów:

Poniższy przykład ilustruje te dwa sposoby tworzenia wystąpienia NumberFormatInfo obiektu i wyświetla wartość jego IsReadOnly właściwości, aby zilustrować, że obiekt nie jest tylko do odczytu.

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

Należy pamiętać, że system operacyjny Windows umożliwia użytkownikowi zastąpienie niektórych NumberFormatInfo wartości właściwości używanych w operacjach formatowania liczbowego i analizowania za pośrednictwem elementu Region i język w Panel sterowania. Na przykład użytkownik, którego kultura to angielski (Stany Zjednoczone), może wybrać wyświetlanie wartości waluty jako 1,1 USD zamiast wartości domyślnej 1,1 USD. Obiekty NumberFormatInfo pobrane w omówionych wcześniej sposobach odzwierciedlają przesłonięcia tych użytkowników. Jeśli jest to niepożądane, można utworzyć NumberFormatInfo obiekt, który nie odzwierciedla przesłonięć użytkownika (i jest to również odczyt/zapis, a nie tylko do odczytu), wywołując CultureInfo.CultureInfo(String, Boolean) konstruktora i podając wartość false argumentu useUserOverride . W poniższym przykładzie przedstawiono ilustrację dla systemu, którego bieżąca kultura to angielski (Stany Zjednoczone) i którego symbol waluty został zmieniony z domyślnej wartości $ na USD.

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

Jeśli właściwość jest ustawiona CultureInfo.UseUserOverride na true, właściwości CultureInfo.DateTimeFormat, CultureInfo.NumberFormati CultureInfo.TextInfo są również pobierane z ustawień użytkownika. Jeśli ustawienia użytkownika są niezgodne z kulturą skojarzoną z obiektem (na przykład jeśli wybrany kalendarz nie jest jednym z CultureInfo kalendarzy wymienionych przez OptionalCalendars właściwość), wyniki metod i wartości właściwości są niezdefiniowane.

Utworzenie wystąpienia obiektu NumberFormatInfo dla niezmiennej kultury

Niezmienna kultura reprezentuje kulturę, w której nie uwzględnia się ustawień kulturowych. Jest on oparty na języku angielskim, ale nie na żadnym konkretnym kraju/regionie języka angielskiego. Chociaż dane określonych kultur mogą być dynamiczne i mogą ulec zmianie w celu odzwierciedlenia nowych konwencji kulturowych lub preferencji użytkownika, dane niezmiennej kultury nie zmieniają się. Obiekt NumberFormatInfo reprezentujący konwencje formatowania niezmiennej kultury może służyć do operacji formatowania, w których ciągi wynikowe nie powinny się różnić w zależności od kultury.

Wystąpienie obiektu reprezentującego konwencje formatowania niezmiennej kultury można utworzyć NumberFormatInfo w następujący sposób:

W poniższym przykładzie użyto każdej z tych metod do utworzenia wystąpienia NumberFormatInfo obiektu reprezentującego niezmienną kulturę. Następnie wskazuje, czy obiekt jest tylko do odczytu,

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

Tworzenie wystąpienia obiektu NumberFormatInfo dla określonej kultury

Określona kultura reprezentuje język, który jest używany w określonym kraju/regionie. Na przykład en-US jest specyficzną kulturą, która reprezentuje język angielski używany w Stany Zjednoczone, a en-CA jest specyficzną kulturą reprezentującą język angielski mówiony w Kanadzie. Wystąpienie obiektu reprezentującego konwencje formatowania określonej kultury można utworzyć NumberFormatInfo w następujący sposób:

W poniższym przykładzie użyto tych czterech sposobów, aby utworzyć NumberFormatInfo obiekt, który odzwierciedla konwencje formatowania kultury Indonezyjskiej (Indonezja). Wskazuje również, czy każdy obiekt jest tylko do odczytu.

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

Tworzenie wystąpienia obiektu NumberFormatInfo dla kultury neutralnej

Neutralna kultura reprezentuje kulturę lub język, który jest niezależny od kraju/regionu. Jest to zazwyczaj element nadrzędny co najmniej jednej konkretnej kultury. Na przykład fr jest neutralną kulturą języka francuskiego i rodzicem kultury fr-FR. Utworzysz NumberFormatInfo obiekt reprezentujący konwencje formatowania kultury neutralnej w taki sam sposób, jak w przypadku tworzenia NumberFormatInfo obiektu reprezentującego konwencje formatowania określonej kultury.

Jednak ze względu na to, że jest ona niezależna od konkretnego kraju/regionu, neutralna kultura nie zawiera informacji o formatowaniu specyficznym dla kultury. Zamiast wypełniać NumberFormatInfo obiekt wartościami ogólnymi, platforma .NET zwraca NumberFormatInfo obiekt, który odzwierciedla konwencje formatowania określonej kultury, która jest elementem podrzędnym kultury neutralnej. Na przykład NumberFormatInfo obiekt neutralnej kultury en odzwierciedla konwencje formatowania kultury en-US, a NumberFormatInfo obiekt kultury fr odzwierciedla konwencje formatowania kultury fr-FR.

Możesz użyć kodu podobnego do poniższego, aby określić, które konwencje formatowania określonej kultury reprezentuje każda neutralna kultura.

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

Dane dynamiczne

Dane specyficzne dla kultury do formatowania wartości liczbowych udostępnianych przez klasę NumberFormatInfo są dynamiczne, podobnie jak dane kulturowe dostarczane przez klasę CultureInfo . Nie należy zakładać stabilności wartości obiektów NumberFormatInfo skojarzonych z określonymi CultureInfo obiektami. Tylko dane dostarczane przez niezmienną kulturę i skojarzony z NumberFormatInfo nim obiekt są stabilne. Inne dane mogą zmieniać się między sesjami aplikacji, a nawet w ramach jednej sesji z następujących powodów:

  • Aktualizacje systemu. Preferencje kulturowe, takie jak symbol waluty lub formaty walut zmieniają się wraz z upływem czasu. W takim przypadku usługa Windows Update zawiera zmiany NumberFormatInfo wartości właściwości dla określonej kultury.

  • Kultury zastępcze. Klasa CultureAndRegionInfoBuilder może służyć do zastępowania danych istniejącej kultury.

  • Kaskadowe zmiany wartości właściwości. Wiele właściwości związanych z kulturą może ulec zmianie w czasie wykonywania, co z kolei powoduje NumberFormatInfo zmianę danych. Na przykład bieżąca kultura może zostać zmieniona programowo lub za pomocą akcji użytkownika. W takim przypadku NumberFormatInfo obiekt zwracany przez CurrentInfo właściwość zmienia się na obiekt skojarzony z bieżącą kulturą.

  • Preferencje użytkownika. Użytkownicy aplikacji mogą zastąpić niektóre wartości skojarzone z bieżącą kulturą systemu za pośrednictwem opcji regionu i języka w Panel sterowania. Na przykład użytkownicy mogą wybrać inny symbol waluty lub inny symbol separatora dziesiętnego. CultureInfo.UseUserOverride Jeśli właściwość jest ustawiona na true (jego wartość domyślna), właściwości NumberFormatInfo obiektu są również pobierane z ustawień użytkownika.

Wszystkie właściwości NumberFormatInfo obiektu, które można zastąpić użytkownika, są inicjowane podczas tworzenia obiektu. Nadal istnieje możliwość niespójności, ponieważ ani tworzenie obiektu, ani proces zastępowania użytkownika nie jest niepodzielne, a odpowiednie wartości mogą ulec zmianie podczas tworzenia obiektu. Jednak te niespójności powinny być niezwykle rzadkie.

Możesz kontrolować, czy przesłonięcia użytkownika są odzwierciedlane w NumberFormatInfo obiektach reprezentujących tę samą kulturę co bieżąca kultura. W poniższej tabeli wymieniono sposoby pobierania NumberFormatInfo obiektu i wskazuje, czy wynikowy obiekt odzwierciedla przesłonięcia użytkownika.

Źródło obiektu CultureInfo i NumberFormatInfo przesłonięcia użytkowników Emocje
CultureInfo.CurrentCulture.NumberFormat Właściwość Tak
NumberFormatInfo.CurrentInfo Właściwość Tak
CultureInfo.CreateSpecificCulture Metoda Tak
CultureInfo.GetCultureInfo Metoda Nie.
CultureInfo(String) Konstruktor Tak
CultureInfo.CultureInfo(String, Boolean) Konstruktor Zależy od wartości parametru useUserOverride

Jeśli nie istnieje przekonujący powód, aby to zrobić inaczej, należy przestrzegać przesłonięć użytkowników podczas używania NumberFormatInfo obiektu w aplikacjach klienckich do formatowania i analizowania danych wejściowych użytkownika lub wyświetlania danych liczbowych. W przypadku aplikacji serwerowych lub aplikacji nienadzorowanych nie należy przestrzegać przesłonięć użytkowników. Jeśli jednak używasz NumberFormatInfo obiektu jawnie lub niejawnie do utrwalania danych liczbowych w postaci ciągu, należy użyć NumberFormatInfo obiektu, który odzwierciedla konwencje formatowania niezmiennej kultury, lub należy określić niestandardowy ciąg formatu liczbowego, który jest używany niezależnie od kultury.

IFormatProvider, NumberformatInfo i formatowanie liczbowe

Obiekt NumberFormatInfo jest używany niejawnie lub jawnie we wszystkich operacjach formatowania liczbowego. Obejmują one wywołania następujących metod:

Wszystkie operacje formatowania liczbowego korzystają z implementacji IFormatProvider . Interfejs IFormatProvider zawiera pojedynczą metodę GetFormat(Type). Jest to metoda wywołania zwrotnego, która przekazuje Type obiekt reprezentujący typ wymagany do dostarczenia informacji o formatowaniu. Metoda jest odpowiedzialna za zwrócenie wystąpienia tego typu lub null, jeśli nie może podać wystąpienia typu. Platforma .NET udostępnia dwie IFormatProvider implementacje formatowania liczb:

Jeśli implementacja IFormatProvider nie zostanie jawnie dostarczona do metody formatowania, CultureInfo używany jest obiekt zwrócony przez CultureInfo.CurrentCulture właściwość reprezentującą bieżącą kulturę.

Poniższy przykład ilustruje relację między interfejsem IFormatProvider a NumberFormatInfo klasą w operacjach formatowania przez zdefiniowanie implementacji niestandardowej IFormatProvider . Metoda GetFormat wyświetla nazwę typu obiektu żądanego przez operację formatowania. Jeśli interfejs żąda NumberFormatInfo obiektu, ta metoda udostępnia NumberFormatInfo obiekt dla bieżącej kultury. Jak pokazano w danych wyjściowych z przykładu, metoda żąda NumberFormatInfo obiektu w celu udostępnienia informacji o formatowaniu, natomiast String.Format(IFormatProvider, String, Object[]) żądania NumberFormatInfo i DateTimeFormatInfo obiekty metody oraz implementacjaICustomFormatter.Decimal.ToString(IFormatProvider)

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

Jeśli implementacja IFormatProvider nie jest jawnie podana w wywołaniu metody formatowania liczbowego, metoda wywołuje CultureInfo.CurrentCulture.GetFormat metodę, która zwraca NumberFormatInfo obiekt odpowiadający bieżącej kulturze.

Ciągi formatów i właściwości NumberFormatInfo

Każda operacja formatowania używa standardowego lub niestandardowego ciągu formatu liczbowego w celu wygenerowania ciągu wynikowego z liczby. W niektórych przypadkach użycie ciągu formatu do wygenerowania ciągu wynikowego jest jawne, jak w poniższym przykładzie. Ten kod wywołuje Decimal.ToString(IFormatProvider) metodę Decimal , aby przekonwertować wartość na wiele różnych reprezentacji ciągów przy użyciu konwencji formatowania kultury en-US.

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

W innych przypadkach użycie ciągu formatu jest niejawne. Na przykład w poniższej metodzie wywołuje metodę domyślną lub bez Decimal.ToString() parametrów wartość Decimal wystąpienia jest formatowana przy użyciu specyfikatora formatu ogólnego ("G") i konwencji bieżącej kultury, co w tym przypadku jest kulturą en-US.

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

Każdy standardowy ciąg formatu liczbowego używa co najmniej jednej NumberFormatInfo właściwości do określenia wzorca lub symboli używanych w ciągu wynikowym. Podobnie każdy niestandardowy specyfikator formatu liczbowego z wyjątkiem "0" i "#" wstawia symbole w ciągu wynikowym zdefiniowanym przez NumberFormatInfo właściwości. W poniższej tabeli wymieniono standardowe i niestandardowe specyfikatory formatu liczbowego oraz skojarzone z NumberFormatInfo nimi właściwości. Aby zmienić wygląd ciągu wynikowego dla określonej kultury, zobacz sekcję Modyfikuj właściwości NumberFormatInfo. Aby uzyskać szczegółowe informacje na temat używania tych specyfikatorów formatu, zobacz Standardowe ciągi formatu liczbowego i Niestandardowe ciągi formatu liczbowego.

Specyfikator formatu Skojarzone właściwości
"C" lub "c" (specyfikator formatu waluty) CurrencyDecimalDigits, aby zdefiniować domyślną liczbę cyfr ułamkowych.

CurrencyDecimalSeparator, aby zdefiniować symbol separatora dziesiętnego.

CurrencyGroupSeparator, aby zdefiniować separator grup lub tysięcy.

CurrencyGroupSizes, aby zdefiniować rozmiary grup całkowitych.

CurrencyNegativePattern, aby zdefiniować wzorzec ujemnych wartości walutowych.

CurrencyPositivePattern, aby zdefiniować wzorzec dodatnich wartości walutowych.

CurrencySymbol, aby zdefiniować symbol waluty.

NegativeSign, aby zdefiniować symbol znaku ujemnego.
"D" lub "d" (specyfikator formatu dziesiętnego) NegativeSign, aby zdefiniować symbol znaku ujemnego.
"E" lub "e" (specyfikator formatu wykładniczego lub naukowego) NegativeSign, aby zdefiniować symbol znaku ujemnego w mantissa i wykładnik.

NumberDecimalSeparator, aby zdefiniować symbol separatora dziesiętnego.

PositiveSign, aby zdefiniować symbol znaku dodatniego w wykładnik.
Specyfikator formatu "F" lub "f" (specyfikator formatu stałego punktu) NegativeSign, aby zdefiniować symbol znaku ujemnego.

NumberDecimalDigits, aby zdefiniować domyślną liczbę cyfr ułamkowych.

NumberDecimalSeparator, aby zdefiniować symbol separatora dziesiętnego.
"G" lub "g" (ogólny specyfikator formatu) NegativeSign, aby zdefiniować symbol znaku ujemnego.

NumberDecimalSeparator, aby zdefiniować symbol separatora dziesiętnego.

PositiveSign, aby zdefiniować symbol znaku dodatniego dla ciągów wyników w formacie wykładniczym.
"N" lub "n" (specyfikator formatu liczb) NegativeSign, aby zdefiniować symbol znaku ujemnego.

NumberDecimalDigits, aby zdefiniować domyślną liczbę cyfr ułamkowych.

NumberDecimalSeparator, aby zdefiniować symbol separatora dziesiętnego.

NumberGroupSeparator, aby zdefiniować symbol separatora grup (tysięcy).

NumberGroupSizes, aby zdefiniować liczbę cyfr całkowitych w grupie.

NumberNegativePattern, aby zdefiniować format wartości ujemnych.
Specyfikator formatu "P" lub "p" (specyfikator formatu procentu) NegativeSign, aby zdefiniować symbol znaku ujemnego.

PercentDecimalDigits, aby zdefiniować domyślną liczbę cyfr ułamkowych.

PercentDecimalSeparator, aby zdefiniować symbol separatora dziesiętnego.

PercentGroupSeparator, aby zdefiniować symbol separatora grup.

PercentGroupSizes, aby zdefiniować liczbę cyfr całkowitych w grupie.

PercentNegativePattern, aby zdefiniować położenie symbolu procentu i symbol ujemny dla wartości ujemnych.

PercentPositivePattern, aby zdefiniować umieszczanie symbolu procentu dla wartości dodatnich.

PercentSymbol, aby zdefiniować symbol procentu.
"R" lub "r" (specyfikator formatu dwukierunkowego) NegativeSign, aby zdefiniować symbol znaku ujemnego.

NumberDecimalSeparator, aby zdefiniować symbol separatora dziesiętnego.

PositiveSign, aby zdefiniować symbol znaku dodatniego w wykładnik.
Specyfikator formatu szesnastkowego "X" lub "x" Brak.
"." (specyfikator formatu niestandardowego punktu dziesiętnego) NumberDecimalSeparator, aby zdefiniować symbol separatora dziesiętnego.
"", (specyfikator formatu niestandardowego separatora grup) NumberGroupSeparator, aby zdefiniować symbol separatora grupy (tysięcy).
"%" (procentowy specyfikator formatu niestandardowego symbolu zastępczego) PercentSymbol, aby zdefiniować symbol procentu.
"^" (specyfikator formatu niestandardowego symbolu zastępczego na mille) PerMilleSymbol, aby zdefiniować symbol młyna.
"E" (specyfikator formatu niestandardowego notacji wykładniczej) NegativeSign, aby zdefiniować symbol znaku ujemnego w mantissa i wykładnik.

PositiveSign, aby zdefiniować symbol znaku dodatniego w wykładnik.

Należy pamiętać, że NumberFormatInfo klasa zawiera właściwość określającą NativeDigits podstawowe 10 cyfr używane przez określoną kulturę. Jednak właściwość nie jest używana w operacjach formatowania; w ciągu wynikowym są używane tylko cyfry łacińskie 0 (U+0030) do 9 (U+0039). Ponadto dla Single wartości , PositiveInfinityNaNDouble i NegativeInfinity, ciąg wynikowy składa się wyłącznie z symboli zdefiniowanych odpowiednio przez NaNSymbolwłaściwości , PositiveInfinitySymboli .NegativeInfinitySymbol

Modyfikowanie właściwości NumberFormatInfo

Właściwości obiektu można zmodyfikować NumberFormatInfo , aby dostosować ciąg wynikowy wygenerowany w operacji formatowania liczbowego. Czynność:

  1. Utwórz kopię NumberFormatInfo odczytu/zapisu obiektu, którego konwencje formatowania chcesz zmodyfikować. Aby uzyskać więcej informacji, zobacz sekcję Wystąpienia obiektu NumberFormatInfo.

  2. Zmodyfikuj właściwość lub właściwości, które są używane do tworzenia żądanego ciągu wynikowego. Aby uzyskać informacje na temat sposobu używania metod formatowania do NumberFormatInfo definiowania ciągów wyników, zobacz sekcję Formatowanie ciągów i właściwości NumberFormatInfo.

  3. Użyj obiektu niestandardowego NumberFormatInfo jako argumentu IFormatProvider w wywołaniach do metod formatowania.

Uwaga

Zamiast dynamicznie modyfikować wartości właściwości kultury za każdym razem, gdy aplikacja jest uruchamiana, można użyć CultureAndRegionInfoBuilder klasy do zdefiniowania kultury niestandardowej (kultury, która ma unikatową nazwę i uzupełnia istniejące kultury) lub kultury zastępczej (używanej zamiast określonej kultury).

W poniższych sekcjach przedstawiono kilka przykładów.

Modyfikowanie symbolu waluty i wzorca

Poniższy przykład modyfikuje NumberFormatInfo obiekt reprezentujący konwencje formatowania kultury en-US. Przypisuje symbol waluty ISO-4217 do CurrencySymbol właściwości i definiuje wzorzec wartości walutowych, który składa się z symbolu waluty, po którym następuje spacja i wartość liczbowa.

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

Formatowanie krajowego numeru identyfikacyjnego

Wiele krajowych numerów identyfikacyjnych składa się wyłącznie z cyfr i dlatego można je łatwo sformatować, modyfikując właściwości NumberFormatInfo obiektu. Na przykład numer ubezpieczenia społecznego w Stany Zjednoczone składa się z 9 cyfr rozmieszczonych w następujący sposób: XXX-XX-XXXX. W poniższym przykładzie przyjęto założenie, że numery ubezpieczenia społecznego są przechowywane jako wartości całkowite i odpowiednio je formatują.

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

Analizowanie ciągów liczbowych

Analizowanie obejmuje konwertowanie ciągu reprezentacji liczby na liczbę. Każdy typ liczbowy na platformie .NET zawiera dwie przeciążone metody analizowania: Parse i TryParse. Metoda Parse konwertuje ciąg na liczbę i zgłasza wyjątek, jeśli konwersja nie powiedzie się. Metoda TryParse konwertuje ciąg na liczbę, przypisuje liczbę do out argumentu i zwraca wartość wskazującą Boolean , czy konwersja zakończyła się pomyślnie.

Metody analizowania niejawnie lub jawnie używają NumberStyles wartości wyliczenia, aby określić, jakie elementy stylu (takie jak separatory grup, separator dziesiętny lub symbol waluty) mogą być obecne w ciągu, jeśli operacja analizowania zakończy się powodzeniem. NumberStyles Jeśli wartość nie jest podana w wywołaniu metody, wartość domyślna to NumberStyles wartość zawierająca Float flagi iAllowThousands, która określa, że przeanalizowany ciąg może zawierać symbole grupy, separator dziesiętny, znak ujemny i znaki odstępu lub może to być reprezentacja ciągu w notacji wykładniczej.

Metody analizowania również niejawnie lub jawnie używają NumberFormatInfo obiektu, który definiuje określone symbole i wzorce, które mogą wystąpić w ciągu do przeanalizowania. NumberFormatInfo Jeśli obiekt nie zostanie podany, wartością domyślną jest NumberFormatInfo bieżąca kultura. Aby uzyskać więcej informacji na temat analizowania, zobacz poszczególne metody analizowania, takie jak Int16.Parse(String), , Int32.Parse(String, NumberStyles)Int64.Parse(String, IFormatProvider), Decimal.Parse(String, NumberStyles, IFormatProvider), , Double.TryParse(String, Double)i BigInteger.TryParse(String, NumberStyles, IFormatProvider, BigInteger).

W poniższym przykładzie przedstawiono wrażliwe na kulturę charakter ciągów analizowania. Próbuje przeanalizować ciąg, który zawiera tysiące separatorów przy użyciu konwencji en-US, fr-FR i niezmiennych kultur. Ciąg, który zawiera przecinek jako separator grupy i kropkę jako separator dziesiętny, nie może przeanalizować w kulturze fr-FR, a ciąg z białym znakiem jako separator grupy i przecinek jako separator dziesiętny nie może przeanalizować w kulturach en-US i niezmiennych.

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)

Analizowanie zwykle występuje w dwóch kontekstach:

  • Jako operacja przeznaczona do konwertowania danych wejściowych użytkownika na wartość liczbową.

  • Jako operacja przeznaczona do zaokrąglania wartości liczbowej; oznacza to, aby deserializować wartość liczbową, która została wcześniej serializowana jako ciąg.

W poniższych sekcjach omówiono te dwie operacje bardziej szczegółowo.

Analizowanie ciągów użytkownika

Podczas analizowania ciągów liczbowych wejściowych przez użytkownika należy zawsze utworzyć NumberFormatInfo wystąpienie obiektu odzwierciedlającego ustawienia kulturowe użytkownika. Aby uzyskać informacje o tworzeniu NumberFormatInfo wystąpienia obiektu, który odzwierciedla dostosowania użytkownika, zobacz sekcję Dane dynamiczne.

Poniższy przykład ilustruje różnicę między operacją analizowania, która odzwierciedla ustawienia kulturowe użytkownika i taką, która nie. W takim przypadku domyślna kultura systemowa to en-US, ale użytkownik zdefiniował wartość "", jako symbol dziesiętny i "." jako separator grupy w Panel sterowania, regionie i języku. Zazwyczaj te symbole są odwrócone w domyślnej kulturze en-US. Gdy użytkownik wprowadzi ciąg, który odzwierciedla ustawienia użytkownika, a ciąg jest analizowany przez NumberFormatInfo obiekt, który odzwierciedla również ustawienia użytkownika (przesłonięcia), operacja analizowania zwraca prawidłowy wynik. Jednak gdy ciąg jest analizowany przez NumberFormatInfo obiekt, który odzwierciedla standardowe ustawienia kulturowe en-US, błędnie symbol przecinka separatora grupy i zwraca niepoprawny wynik.

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

Serializowanie i deserializowanie danych liczbowych

Gdy dane liczbowe są serializowane w formacie ciągu, a później deserializowane i analizowane, ciągi powinny być generowane i analizowane przy użyciu konwencji niezmiennej kultury. Operacje formatowania i analizowania nigdy nie powinny odzwierciedlać konwencji określonej kultury. Jeśli są używane ustawienia specyficzne dla kultury, przenośność danych jest ściśle ograniczona; Można ją pomyślnie zdeserializować tylko w wątku, którego ustawienia specyficzne dla kultury są identyczne z ustawieniami wątku, na którym została serializowana. W niektórych przypadkach oznacza to, że dane nie mogą być nawet pomyślnie zdeserializowane w tym samym systemie, w którym zostały serializowane.

Poniższy przykład ilustruje, co może się zdarzyć, gdy ta zasada zostanie naruszona. Wartości zmiennoprzecinkowe w tablicy są konwertowane na ciągi, gdy bieżący wątek używa ustawień specyficznych dla kultury kultury en-US. Dane są następnie analizowane przez wątek, który używa ustawień specyficznych dla kultury kultury kultury pt-BR kultury. W takim przypadku, chociaż każda operacja analizowania powiedzie się, dane nie są pomyślnie wykonywane i występują uszkodzenia danych. W innych przypadkach operacja analizowania może zakończyć się niepowodzeniem FormatException i może zostać zgłoszony wyjątek.

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