Поделиться через


Класс NumberFormatInfo

В этой статье приводятся дополнительные замечания к справочной документации по этому API.

Класс NumberFormatInfo содержит сведения, относящиеся к языку и региональным параметрам, которые используются при форматировании и анализе числовых значений. Эти сведения включают символ валюты, десятичный символ, символ разделителя групп и символы для положительных и отрицательных знаков.

Создание экземпляра объекта NumberFormatInfo

Можно создать экземпляр NumberFormatInfo объекта, представляющего соглашения о форматировании текущего языка и региональных параметров, инвариантного языка и региональных параметров, определенного языка и региональных параметров или нейтрального языка и региональных параметров.

Создание экземпляра объекта NumberFormatInfo для текущего языка и региональных параметров

Вы можете создать экземпляр NumberFormatInfo объекта для текущего языка и региональных параметров любым из следующих способов. В каждом случае возвращенный NumberFormatInfo объект доступен только для чтения.

  • Извлекая объект, представляющий текущий CultureInfo язык и региональные параметры из CultureInfo.CurrentCulture свойства, и извлекая CultureInfo объект из его CultureInfo.NumberFormat свойства.

  • Извлекая объект, NumberFormatInfo возвращаемый свойством static (Sharedв Visual Basic). CurrentInfo

  • Вызывая GetInstance метод с CultureInfo объектом, который представляет текущий язык и региональные параметры.

В следующем примере используются три способа создания NumberFormatInfo объектов, представляющих соглашения о форматировании текущего языка и региональных параметров. Он также извлекает значение IsReadOnly свойства, иллюстрирующий, что каждый объект доступен только для чтения.

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

Вы можете создать объект, доступный NumberFormatInfo для записи, который представляет соглашения текущего языка и региональных параметров любым из следующих способов:

  • Извлекая объект в любом из способов, показанных в предыдущем примере кода, и вызывая NumberFormatInfoClone метод для возвращаемого NumberFormatInfo объекта. При этом создается копия исходного NumberFormatInfo объекта, за исключением того, что его IsReadOnly свойство имеет falseзначение.

  • Вызывая CultureInfo.CreateSpecificCulture метод для создания CultureInfo объекта, представляющего текущий язык и региональные параметры, а затем используя его CultureInfo.NumberFormat свойство для получения NumberFormatInfo объекта.

В следующем примере показаны два способа создания экземпляра NumberFormatInfo объекта и отображение значения его IsReadOnly свойства для иллюстрации того, что объект не доступен только для чтения.

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

Обратите внимание, что операционная система Windows позволяет пользователю переопределить некоторые NumberFormatInfo значения свойств, используемые в числовых операциях форматирования и синтаксического анализа с помощью элемента "Регион" и "Язык" в панель управления. Например, пользователь, язык и региональные параметры которого — английский (США) могут отображать значения валют как 1,1 ДОЛЛ. США вместо 1,1 долл. США по умолчанию. Объекты NumberFormatInfo , полученные ранее, отражают переопределения этих пользователей. Если это нежелательно, можно создать NumberFormatInfo объект, который не отражает переопределения пользователей (а также чтение и запись, а не только для чтения), вызвав CultureInfo.CultureInfo(String, Boolean) конструктор и указав значение аргумента falseuseUserOverride . В следующем примере показана иллюстрация для системы, текущая культура которой — английский (США) и символ валюты которого был изменен с значения по умолчанию $ на 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: $

CultureInfo.UseUserOverride Если для свойства задано trueзначение , CultureInfo.NumberFormatсвойства CultureInfo.DateTimeFormat, а CultureInfo.TextInfo также извлекаются из параметров пользователя. Если параметры пользователя несовместимы с языком и региональными параметрами, связанными с CultureInfo объектом (например, если выбранный календарь не является одним из календарей, перечисленных OptionalCalendars свойством), результаты методов и значения свойств не определены.

Создание экземпляра объекта NumberFormatInfo для инвариантного языка и региональных параметров

Инвариантная культура представляет язык и региональные параметры, не зависящие от языка и региональных параметров. Он основан на английском языке, но не на какой-либо конкретной англоязычной стране или регионе. Хотя данные конкретных языков и региональных параметров могут быть динамическими и могут изменяться в соответствии с новыми культурными соглашениями или предпочтениями пользователей, данные инвариантного языка и региональных параметров не изменяются. Объект NumberFormatInfo , представляющий соглашения о форматировании инвариантного языка и региональных параметров, можно использовать для операций форматирования, в которых результирующих строк не должно отличаться от языка и региональных параметров.

Вы можете создать экземпляр NumberFormatInfo объекта, представляющего соглашения о форматировании инвариантного языка и региональных параметров следующим образом:

В следующем примере каждый из этих методов используется для создания экземпляра NumberFormatInfo объекта, представляющего инвариантный язык и региональные параметры. Затем он указывает, доступен ли объект только для чтения.

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

Создание экземпляра объекта NumberFormatInfo для определенного языка и региональных параметров

Определенный язык и региональные параметры представляют язык, который говорится в определенной стране или регионе. Например, en-US — это определенная культура, представляющая английский язык, который говорится в США, а en-CA — это определенная культура, представляющая английский язык, который говорится в Канаде. Вы можете создать экземпляр NumberFormatInfo объекта, представляющего соглашения о форматировании определенного языка и региональных параметров следующим образом:

В следующем примере используются четыре способа создания NumberFormatInfo объекта, который отражает соглашения о форматировании индонезийской культуры (Индонезия). Он также указывает, доступен ли каждый объект только для чтения.

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

Создание экземпляра объекта NumberFormatInfo для нейтрального языка и региональных параметров

Нейтральный язык и региональные параметры представляют язык или язык, не зависящий от страны или региона. Обычно это родитель одного или нескольких конкретных языков и региональных параметров. Например, fr является нейтральным языком для французского языка и родительским языком fr-FR. Вы создаете объект, представляющий соглашения о форматировании нейтрального языка и региональных параметров таким же образом, как NumberFormatInfo создается NumberFormatInfo объект, представляющий соглашения о форматировании определенного языка и региональных параметров.

Тем не менее, поскольку она не зависит от конкретной страны или региона, нейтральный язык и региональные параметры не имеют сведений о форматировании. Вместо заполнения NumberFormatInfo объекта универсальными значениями .NET возвращает NumberFormatInfo объект, который отражает соглашения о форматировании определенного языка и региональных параметров, который является дочерним элементом нейтрального языка и региональных параметров. Например, NumberFormatInfo объект для нейтрального языка и региональных параметров отражает соглашения о форматировании языка и региональных параметров en-US, а NumberFormatInfo объект для языка и региональных параметров fr отражает соглашения о форматировании языка fr-FR.

Вы можете использовать код, как показано ниже, чтобы определить, какие соглашения о форматировании определенного языка и региональных параметров представляют каждый нейтральный язык и региональные параметры.

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

Динамические данные

Данные, зависящие от языка и региональных параметров, для форматирования числовых значений, предоставляемых NumberFormatInfo классом, являются динамическими, как и региональные данные, предоставляемые классом CultureInfo . Не следует делать никаких предположений о стабильности значений для NumberFormatInfo объектов, связанных с конкретными CultureInfo объектами. Только данные, предоставляемые инвариантным языком и языком и связанным NumberFormatInfo объектом, стабильны. Другие данные могут изменяться между сеансами приложений или даже в рамках одного сеанса по следующим причинам:

  • Обновления системы. Культурные предпочтения, такие как символ валюты или форматы валют с течением времени. В этом случае Обновл. Windows включает изменения NumberFormatInfo в значение свойства для определенного языка и региональных параметров.

  • Язык и региональные параметры замены. Класс CultureAndRegionInfoBuilder можно использовать для замены данных существующего языка и региональных параметров.

  • Каскадные изменения значений свойств. Ряд свойств, связанных с языком и региональными параметрами, может изменяться во время выполнения, что, в свою очередь, приводит NumberFormatInfo к изменению данных. Например, текущий язык и региональные параметры можно изменить программным способом или с помощью действия пользователя. Когда это происходит, объект, возвращаемый свойствомCurrentInfo, NumberFormatInfo изменяется на объект, связанный с текущим языком и региональными параметрами.

  • Параметры пользователя. Пользователи приложения могут переопределить некоторые значения, связанные с текущим языком и региональными параметрами системы, через регион и языковые параметры в панель управления. Например, пользователи могут выбрать другой символ валюты или другой десятичный разделитель. CultureInfo.UseUserOverride Если для свойства задано true значение (значение по умолчанию), свойства NumberFormatInfo объекта также извлекаются из параметров пользователя.

Все переопределиемые пользователем свойства NumberFormatInfo объекта инициализированы при создании объекта. Существует по-прежнему вероятность несоответствия, поскольку ни создание объекта, ни процесс переопределения пользователя атомарен, а соответствующие значения могут изменяться во время создания объекта. Однако эти несоответствия должны быть крайне редкими.

Вы можете контролировать, отражаются ли переопределения пользователей в NumberFormatInfo объектах, представляющих тот же язык и региональные параметры, что и текущий язык и региональные параметры. В следующей таблице перечислены способы NumberFormatInfo извлечения объекта и указывает, отражает ли результирующий объект переопределение пользователей.

Источник объекта CultureInfo и NumberFormatInfo Рефлексия переопределения пользователей
Свойство CultureInfo.CurrentCulture.NumberFormat Да
Свойство NumberFormatInfo.CurrentInfo Да
CultureInfo.CreateSpecificCultureМетод Да
CultureInfo.GetCultureInfoМетод No
Конструктор CultureInfo(String) Да
Конструктор CultureInfo.CultureInfo(String, Boolean) Зависит от значения useUserOverride параметра

Если в противном случае не существует убедительных причин, следует учитывать переопределения пользователей при использовании NumberFormatInfo объекта в клиентских приложениях для форматирования и анализа входных данных пользователей или отображения числовых данных. Для серверных приложений или автоматических приложений не следует учитывать переопределения пользователей. Однако если объект используется NumberFormatInfo явно или неявно для сохранения числовых данных в строковой форме, следует либо использовать NumberFormatInfo объект, который отражает соглашения о форматировании инвариантного языка и региональных параметров, либо указать настраиваемую строку числового формата, используемую независимо от языка и региональных параметров.

IFormatProvider, NumberFormatInfo и числовое форматирование

NumberFormatInfo Объект используется неявно или явно во всех числовых операциях форматирования. К ним относятся вызовы следующих методов:

Все числовые операции форматирования используют реализацию IFormatProvider . Интерфейс IFormatProvider включает один метод. GetFormat(Type) Это метод обратного Type вызова, который передает объект, представляющий тип, необходимый для предоставления сведений о форматировании. Метод отвечает за возврат экземпляра этого типа или null, если он не может предоставить экземпляр типа. .NET предоставляет две IFormatProvider реализации для форматирования чисел:

  • Класс CultureInfo , представляющий определенный язык и региональные параметры (или определенный язык в определенной стране или регионе). В операции числового форматирования метод возвращает NumberFormatInfo объект, CultureInfo.GetFormat связанный с его CultureInfo.NumberFormat свойством.

  • Класс NumberFormatInfo , предоставляющий сведения о соглашениях форматирования связанного языка и региональных параметров. Метод NumberFormatInfo.GetFormat возвращает сам экземпляр.

IFormatProvider Если реализация не предоставляется методу форматирования явным образом, используется объект, CultureInfo возвращаемый CultureInfo.CurrentCulture свойством, представляющим текущий язык и региональные параметры.

В следующем примере показана связь между интерфейсом IFormatProvider и NumberFormatInfo классом в операциях форматирования путем определения пользовательской IFormatProvider реализации. Его GetFormat метод отображает имя типа объекта, запрошенного операцией форматирования. Если интерфейс запрашивает NumberFormatInfo объект, этот метод предоставляет NumberFormatInfo объект для текущего языка и региональных параметров. Как показано в выходных данных из примера, Decimal.ToString(IFormatProvider) метод запрашивает NumberFormatInfo объект для предоставления сведений о форматировании, в то время как String.Format(IFormatProvider, String, Object[]) запросы NumberFormatInfo метода и DateTimeFormatInfo объекты, а также ICustomFormatter реализация.

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

IFormatProvider Если реализация не предоставляется явным образом в вызове метода числового форматирования, метод вызывает CultureInfo.CurrentCulture.GetFormat метод, который возвращает NumberFormatInfo объект, соответствующий текущему языку и региональным параметрам.

Форматирование строк и свойств NumberFormatInfo

Каждая операция форматирования использует стандартную или настраиваемую числовую строку для создания результирующих строк из числа. В некоторых случаях использование строки форматирования для создания результирующих строк явно, как показано в следующем примере. Этот код вызывает Decimal.ToString(IFormatProvider) метод для преобразования Decimal значения в несколько различных строковых представлений с помощью соглашений о форматировании языка и региональных параметров 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

В других случаях использование строки формата неявно. Например, в следующем методе вызывается метод по умолчанию или без параметров, значение Decimal экземпляра отформатировано с помощью общего описателя формата ("G") и соглашений текущего языка и региональных параметров, которые в данном случае являются языком и региональных параметров Decimal.ToString() 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

Каждая стандартная числовая строка использует одно или несколько NumberFormatInfo свойств для определения шаблона или символов, используемых в строке результата. Аналогичным образом каждый описатель пользовательского числового формата, кроме символов "0" и "#" вставки в результирующую строку, определяемую свойствами NumberFormatInfo . В следующей таблице перечислены описатели стандартного и пользовательского числовых форматов и связанные NumberFormatInfo с ними свойства. Чтобы изменить внешний вид строки результатов для определенного языка и региональных параметров, см . раздел свойств Change NumberFormatInfo. Дополнительные сведения об использовании этих описателей формата см. в разделе "Стандартные числовые строки формата" и "Настраиваемые числовые строки".

Спецификатор формата Связанные свойства
"C" или "c" (описатель формата валюты) CurrencyDecimalDigits, чтобы определить число дробных цифр по умолчанию.

CurrencyDecimalSeparator, для определения символа десятичного разделителя.

CurrencyGroupSeparator, чтобы определить группу или разделитель тысяч.

CurrencyGroupSizes, чтобы определить размеры целочисленных групп.

CurrencyNegativePattern, чтобы определить шаблон отрицательных валютных значений.

CurrencyPositivePattern, чтобы определить шаблон положительных валютных значений.

CurrencySymbol, чтобы определить символ валюты.

NegativeSign, для определения знака минус.
"D" или "d" (описатель десятичного формата) NegativeSign, для определения знака минус.
"E" или "e" (экспоненциальный или научный описатель формата) NegativeSign, чтобы определить символ отрицательного знака в мантиссе и экспоненте.

NumberDecimalSeparator, для определения символа десятичного разделителя.

PositiveSign, чтобы определить символ положительного знака в экспоненте.
"F" или "f" (описатель формата фиксированной точки) NegativeSign, для определения знака минус.

NumberDecimalDigits, чтобы определить число дробных цифр по умолчанию.

NumberDecimalSeparator, для определения символа десятичного разделителя.
"G" или "g" (описатель общего формата) NegativeSign, для определения знака минус.

NumberDecimalSeparator, для определения символа десятичного разделителя.

PositiveSign, чтобы определить символ положительного знака для строк результатов в экспоненциальном формате.
"N" или "n" (описатель формата чисел) NegativeSign, для определения знака минус.

NumberDecimalDigits, чтобы определить число дробных цифр по умолчанию.

NumberDecimalSeparator, для определения символа десятичного разделителя.

NumberGroupSeparator, чтобы определить символ разделителя групп (тысячи).

NumberGroupSizes, чтобы определить число целочисленных цифр в группе.

NumberNegativePattern, чтобы определить формат отрицательных значений.
"P" или "p" (описатель формата процента) NegativeSign, для определения знака минус.

PercentDecimalDigits, чтобы определить число дробных цифр по умолчанию.

PercentDecimalSeparator, для определения символа десятичного разделителя.

PercentGroupSeparator, чтобы определить символ разделителя групп.

PercentGroupSizes, чтобы определить число целочисленных цифр в группе.

PercentNegativePattern, чтобы определить размещение символа процента и отрицательного символа для отрицательных значений.

PercentPositivePattern, чтобы определить размещение символа процента для положительных значений.

PercentSymbol, чтобы определить символ процента.
"R" или "r" (описатель формата кругового пути) NegativeSign, для определения знака минус.

NumberDecimalSeparator, для определения символа десятичного разделителя.

PositiveSign, чтобы определить символ положительного знака в экспоненте.
"X" или "x" (описатель шестнадцатеричного формата) Нет.
"." (описатель пользовательского формата десятичной запятой) NumberDecimalSeparator, для определения символа десятичного разделителя.
"," (описатель пользовательского формата разделителя групп) NumberGroupSeparator, чтобы определить символ разделителя группы (тысячи).
"%" (описатель пользовательского формата в процентах) PercentSymbol, чтобы определить символ процента.
""." (на милле заполнитель настраиваемого описатель формата) PerMilleSymbol, чтобы определить символ на милле.
"E" (описатель пользовательского формата экспоненциальной нотации) NegativeSign, чтобы определить символ отрицательного знака в мантиссе и экспоненте.

PositiveSign, чтобы определить символ положительного знака в экспоненте.

Обратите внимание, что NumberFormatInfo класс содержит NativeDigits свойство, указывающее базовые 10 цифр, используемых определенным языком и региональными параметрами. Однако свойство не используется в операциях форматирования; В результирующем строке используются только цифры basic Latin 0 (U+0030) –9 (U+0039). Кроме того, для Single и значений NaN, PositiveInfinityа DoubleNegativeInfinityтакже строка результатов состоит исключительно из символов, определенных NaNSymbolPositiveInfinitySymbolNegativeInfinitySymbol и свойствами соответственно.

Изменение свойств NumberFormatInfo

Вы можете изменить свойства NumberFormatInfo объекта, чтобы настроить строку результатов, созданную в операции числового форматирования. Для этого:

  1. Создайте копию объекта с чтением и записью NumberFormatInfo , соглашения о форматировании которого необходимо изменить. Дополнительные сведения см. в разделе "Создание экземпляра объекта NumberFormatInfo".

  2. Измените свойство или свойства, используемые для создания требуемой строки результата. Сведения о том, как методы форматирования используют NumberFormatInfo свойства для определения строк результатов, см. в разделе свойств Format и NumberFormatInfo.

  3. Используйте пользовательский NumberFormatInfo объект в качестве аргумента IFormatProvider в вызовах методов форматирования.

Примечание.

Вместо динамического изменения значений свойств языка и региональных параметров при каждом запуске приложения можно использовать CultureAndRegionInfoBuilder класс для определения пользовательского языка и региональных параметров (языка и региональных параметров, который дополняет существующие региональные параметры) или замещающего языка и региональных параметров (который используется вместо определенного языка и региональных параметров).

В следующих разделах приведены некоторые примеры.

Изменение символа и шаблона валюты

В следующем примере объект NumberFormatInfo изменяет объект, представляющий соглашения о форматировании языка и региональных параметров en-US. Он назначает символ CurrencySymbol валюты ISO-4217 свойству и определяет шаблон для значений валют, состоящих из символа валюты, за которым следует пробел и числовое значение.

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

Форматирование национального идентификационный номер

Многие национальные идентификационные номера состоят исключительно из цифр, поэтому их можно легко отформатировать, изменив свойства NumberFormatInfo объекта. Например, номер социального страхования в США состоит из 9 цифр, расположенных следующим образом: XXX-XX-XXXX В следующем примере предполагается, что номера социального страхования хранятся в виде целых значений и форматируют их соответствующим образом.

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

Анализ числовых строк

Синтаксический анализ включает преобразование строкового представления числа в число. Каждый числовой тип в .NET включает два перегруженных метода синтаксического анализа: Parse и TryParse. Метод Parse преобразует строку в число и создает исключение, если преобразование завершается ошибкой. Метод TryParse преобразует строку в число, назначает число out аргументу и возвращает Boolean значение, указывающее, успешно ли выполнено преобразование.

Методы синтаксического анализа неявно или явно используют NumberStyles значение перечисления, чтобы определить, какие элементы стиля (например, разделители групп, десятичный разделитель или символ валюты) могут присутствовать в строке, если операция синтаксического анализа будет выполнена успешно. NumberStyles Если значение не указано в вызове метода, значение по умолчанию — это NumberStyles значение, включающее Float и AllowThousands флаги, указывающее, что синтаксическая строка может включать символы групп, десятичный разделитель, отрицательный знак и символы пробела, или это может быть строковое представление числа в экспоненциальной нотации.

Методы синтаксического анализа также неявно или явно используют NumberFormatInfo объект, определяющий определенные символы и шаблоны, которые могут возникать в строке для анализа. NumberFormatInfo Если объект не указан, по умолчанию используется NumberFormatInfo текущий язык и региональные параметры. Дополнительные сведения о синтаксическом анализе см. в отдельных методах синтаксического анализа, таких как Int16.Parse(String), Int32.Parse(String, NumberStyles), Int64.Parse(String, IFormatProvider), Decimal.Parse(String, NumberStyles, IFormatProvider)Double.TryParse(String, Double)и BigInteger.TryParse(String, NumberStyles, IFormatProvider, BigInteger).

В следующем примере показан характер анализа строк с учетом языка и региональных параметров. Он пытается проанализировать строку, включающую тысячи разделителей с помощью соглашений en-US, fr-FR и инвариантных региональных параметров. Строка, содержащая запятую в качестве разделителя групп и период в качестве десятичного разделителя, не выполняет синтаксический анализ в языке и региональных параметрах fr-FR, а строка с пробелом в качестве разделителя групп и запятой в качестве десятичного разделителя не может анализироваться в языках и региональных параметров en-US и инвариантных языках.

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)

Анализ обычно происходит в двух контекстах:

  • Как операция, предназначенная для преобразования входных данных пользователей в числовое значение.

  • Как операция, предназначенная для кругового пути числового значения; То есть для десериализации числового значения, ранее сериализованного в виде строки.

В следующих разделах подробно рассматриваются эти две операции.

Анализ строк пользователей

При синтаксическом анализе числовых строк, входных пользователем, всегда следует создать экземпляр NumberFormatInfo объекта, который отражает культурные параметры пользователя. Сведения о создании экземпляра NumberFormatInfo объекта, который отражает настройки пользователей, см. в разделе динамических данных .

В следующем примере показано различие между операцией синтаксического анализа, которая отражает региональные параметры пользователя и ту, которая не соответствует. В этом случае системный язык и региональные параметры по умолчанию — en-US, но пользователь определил "", как десятичный символ и "." в качестве разделителя групп в панель управления, регионе и языке. Как правило, эти символы обратно в языке и региональных параметров en-US по умолчанию. Когда пользователь вводит строку, которая отражает параметры пользователя, и строка анализируется объектом, который также отражает параметры пользователя (переопределяет), операция синтаксического NumberFormatInfo анализа возвращает правильный результат. Однако если строка анализируется объектом, который отражает стандартные региональные параметры en-US, он ошибается NumberFormatInfo символом запятой для разделителя групп и возвращает неправильный результат.

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

Сериализация и десериализация числовых данных

При сериализации числовых данных в строковом формате и последующем десериализации и синтаксическом анализе строки следует создавать и анализировать с помощью соглашений инвариантного языка и региональных параметров. Операции форматирования и синтаксического анализа никогда не должны отражать соглашения определенного языка и региональных параметров. Если используются параметры, зависящие от языка и региональных параметров, переносимость данных строго ограничена; его можно успешно десериализировать только в потоке, параметры которого зависят от параметров языка и региональных параметров, идентичных параметрам потока, на котором она была сериализована. В некоторых случаях это означает, что данные даже не могут быть успешно десериализированы в той же системе, в которой она была сериализована.

В следующем примере показано, что может произойти при нарушении этого принципа. Значения с плавающей запятой в массиве преобразуются в строки, когда текущий поток использует параметры языка и региональных параметров языка и региональных параметров en-US. Затем данные анализируются потоком, использующими параметры языка и региональных параметров pt-BR. В этом случае, хотя каждая операция синтаксического анализа завершается успешно, данные не успешно выполняются и возникают повреждения данных. В других случаях операция синтаксического анализа может завершиться ошибкой, и FormatException может быть вызвано исключение.

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