Classe NumberFormatInfo

Cet article vous offre des remarques complémentaires à la documentation de référence pour cette API.

La classe NumberFormatInfo contient des informations propres à la culture utilisées lorsque vous mettez en forme et analysez des valeurs numériques. Ces informations comprennent le symbole monétaire, le symbole décimal, le symbole de séparateur de groupes et les symboles des signes positif et négatif.

Instancier un objet NumberFormatInfo

Vous pouvez instancier un objet NumberFormatInfo qui représente les conventions de mise en forme de la culture actuelle, de la culture invariante, d’une culture spécifique ou d’une culture neutre.

Instancier un objet NumberFormatInfo pour la culture actuelle

Vous pouvez instancier un objet NumberFormatInfo pour la culture actuelle de l’une des façons suivantes. Dans chaque cas, l’objet NumberFormatInfo retourné est en lecture seule.

L’exemple suivant utilise ces trois méthodes pour créer des objets NumberFormatInfo qui représentent les conventions de mise en forme de la culture actuelle. Il récupère également la valeur de la propriété IsReadOnly pour montrer que chaque objet est en lecture seule.

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

Vous pouvez créer un objet NumberFormatInfo accessible en écriture qui représente les conventions de la culture actuelle de l’une des manières suivantes :

L’exemple suivant illustre ces deux façons d’instancier un objet NumberFormatInfo et affiche la valeur de sa propriété IsReadOnly pour montrer que l’objet n’est pas en lecture seule.

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

Notez que le système d’exploitation Windows permet à l’utilisateur de remplacer certaines des valeurs de propriété NumberFormatInfo utilisées dans les opérations de mise en forme et d’analyse numériques via l’élément Région et langue dans le Panneau de configuration. Par exemple, il est possible qu’un utilisateur dont la culture est anglaise (États-Unis) choisisse d’afficher des valeurs monétaires de type 1,1 USD plutôt que la valeur par défaut de 1,1 $. Les objets NumberFormatInfo récupérés de la manière précédemment décrite reflètent tous ces remplacements d’utilisateur. Si ceci n’est pas souhaitable, vous pouvez créer un objet NumberFormatInfo qui ne reflète pas les remplacements d’utilisateur (et qui est également en lecture/écriture plutôt qu’en lecture seule) en appelant le constructeur CultureInfo.CultureInfo(String, Boolean) et en spécifiant une valeur false pour l’argument useUserOverride. L’exemple suivant fournit une illustration pour un système dont la culture actuelle est anglaise (États-Unis) et dont la valeur par défaut du symbole monétaire des $ a été remplacée par 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: $

Si la propriété CultureInfo.UseUserOverride a la valeur true, les propriétés CultureInfo.DateTimeFormat, CultureInfo.NumberFormat et CultureInfo.TextInfo sont également récupérées à partir des paramètres utilisateur. Si les paramètres utilisateur ne sont pas compatibles avec la culture associée à l’objet CultureInfo (par exemple, si le calendrier sélectionné n’est pas l’un des calendriers répertoriés par la propriété OptionalCalendars), les résultats des méthodes et les valeurs des propriétés ne sont pas définis.

Instancier un objet NumberFormatInfo pour la culture invariante

La culture invariante représente une culture qui est indépendante de la culture. Elle est basée sur la langue anglaise, mais pas sur un pays ou une région anglophone spécifique. Même si les données de cultures spécifiques peuvent être dynamiques et peuvent changer pour refléter de nouvelles conventions culturelles ou préférences utilisateur, les données de la culture invariante ne changent pas. Un objet NumberFormatInfo, qui représente les conventions de mise en forme de la culture invariante, peut être utilisé pour des opérations de mise en forme dans lesquelles les chaînes de résultats ne doivent pas varier selon la culture.

Vous pouvez instancier un objet NumberFormatInfo qui représente les conventions de mise en forme de la culture invariante des façons suivantes :

L’exemple suivant utilise chacune de ces méthodes pour instancier un objet NumberFormatInfo qui représente la culture invariante. Il indique ensuite si l’objet est en lecture seule,

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

Instancier un objet NumberFormatInfo pour une culture spécifique

Une culture spécifique représente une langue parlée dans un pays ou une région spécifique. Par exemple, en-US est une culture spécifique qui représente la langue anglaise parlée aux États-Unis, et en-CA est une culture spécifique qui représente la langue anglaise parlée au Canada. Vous pouvez instancier un objet NumberFormatInfo qui représente les conventions de mise en forme d’une culture spécifique des façons suivantes :

L’exemple suivant utilise ces quatre méthodes pour créer un objet NumberFormatInfo qui reflète les conventions de mise en forme de la culture indonésienne (Indonésie). Il indique également si chaque objet est en lecture seule.

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

Instancier un objet NumberFormatInfo pour une culture neutre

Une culture neutre représente une culture ou une langue indépendante d’un pays ou d’une région. Il s’agit généralement du parent d’une ou de plusieurs cultures spécifiques. Par exemple, fr est une culture neutre pour la langue française et le parent de la culture fr-FR. Vous créez un objet NumberFormatInfo qui représente les conventions de mise en forme d’une culture neutre de la même manière que vous créez un objet NumberFormatInfo qui représente les conventions de mise en forme d’une culture spécifique.

Toutefois, étant donné qu’elle est indépendante d’un pays ou d’une région spécifique, une culture neutre ne contient pas d’informations de mise en forme propres à la culture. Au lieu de remplir l’objet NumberFormatInfo avec des valeurs génériques, .NET retourne un objet NumberFormatInfo reflétant les conventions de mise en forme d’une culture spécifique qui est un enfant de la culture neutre. Par exemple, l’objet NumberFormatInfo de la culture en neutre reflète les conventions de mise en forme de la culture en-US, et l’objet NumberFormatInfo de la culture fr reflète les conventions de mise en forme de la culture fr-FR.

Vous pouvez utiliser du code semblable à ce qui suit pour déterminer les conventions de mise en forme de la culture spécifique que chaque culture neutre représente.

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

Données dynamiques

Les données spécifiques à la culture pour la mise en forme de valeurs numériques fournies par la classe NumberFormatInfo sont dynamiques, tout comme les données culturelles fournies par la classe CultureInfo. Vous ne devez pas faire d’hypothèses sur la stabilité des valeurs des objets NumberFormatInfo qui sont associés à des objets CultureInfo particuliers. Seules les données fournies par la culture invariante et son objet NumberFormatInfo associé sont stables. D’autres données peuvent changer d’une session d’application à une autre, ou même au cours d’une seule session, pour les raisons suivantes :

  • Mises à jour système. Les préférences culturelles, telles que le symbole monétaire ou les formats monétaires changent au fil du temps. Dans ce cas, Windows Update comprend les modifications apportées à la valeur de propriété NumberFormatInfo pour une culture particulière.

  • Cultures de remplacement. La classe CultureAndRegionInfoBuilder peut être utilisée pour remplacer les données d’une culture existante.

  • Modifications en cascade de valeurs de propriété. Un certain nombre de propriétés liées à une culture peuvent changer au moment de l’exécution, ce qui entraîne la modification des données NumberFormatInfo. Par exemple, la culture actuelle peut être changée par programmation ou via une action de l’utilisateur. Dans ce cas, l’objet NumberFormatInfo retourné par la propriété CurrentInfo devient un objet associé à la culture actuelle.

  • Préférences utilisateur. Les utilisateurs de votre application peuvent remplacer certaines des valeurs associées à la culture système actuelle via les options régionales et linguistiques du Panneau de configuration. Par exemple, il est possible que les utilisateurs choisissent un autre symbole monétaire ou un symbole de séparateur décimal différent. Si la propriété CultureInfo.UseUserOverride est définie sur true (sa valeur par défaut), les propriétés de l’objet NumberFormatInfo sont également récupérées à partir des paramètres utilisateur.

Toutes les propriétés remplaçables par l’utilisateur d’un objet NumberFormatInfo sont initialisées lors de la création de l’objet. Il existe toujours une possibilité d’incohérence, car ni la création d’objet, ni le processus de remplacement de l’utilisateur ne sont atomiques et les valeurs pertinentes peuvent changer lors de la création de l’objet. Ces incohérences doivent être cependant extrêmement rares.

Vous pouvez contrôler si les remplacements utilisateur sont reflétés dans des objets NumberFormatInfo qui représentent la même culture que la culture actuelle. Le tableau suivant répertorie les façons dont un objet NumberFormatInfo peut être récupéré et indique si l’objet résultant reflète les remplacements de l’utilisateur.

Source des objets CultureInfo et NumberFormatInfo Reflète les remplacements des utilisateurs
Propriété CultureInfo.CurrentCulture.NumberFormat Oui
Propriété NumberFormatInfo.CurrentInfo Oui
Méthode CultureInfo.CreateSpecificCulture Oui
Méthode CultureInfo.GetCultureInfo Non
Constructeur CultureInfo(String) Oui
Constructeur CultureInfo.CultureInfo(String, Boolean) Dépend de la valeur du paramètre useUserOverride

À moins qu’il existe une raison irréfutable pour agir autrement, vous devez respecter les remplacements d’utilisateur lorsque vous utilisez l’objet NumberFormatInfo dans des applications clientes afin de mettre en forme et analyser l’entrée d’utilisateur ou pour afficher des données numériques. Pour les applications serveur ou les applications sans assistance, vous ne devez pas respecter les remplacements de l’utilisateur. Toutefois, si vous utilisez l’objet NumberFormatInfo de manière explicite ou implicite pour conserver des données numériques sous forme de chaîne, vous devez utiliser un objet NumberFormatInfo qui reflète les conventions de mise en forme de la culture invariante, ou vous devez spécifier une chaîne de format numérique personnalisée que vous utilisez quelle que soit la culture.

IFormatProvider, NumberFormatInfo et mise en forme numérique

Un objet NumberFormatInfo est utilisé implicitement ou explicitement dans toutes les opérations de mise en forme numérique. Il s’agit notamment des appels aux méthodes suivantes :

Toutes les opérations de mise en forme numérique utilisent une implémentation IFormatProvider. L’interface IFormatProvider comprend une seule méthode, GetFormat(Type). Il s’agit d’une méthode de rappel qui reçoit un objet Type représentant le type nécessaire pour fournir des informations de mise en forme. La méthode est chargée de retourner une instance de ce type ou null, si elle ne peut pas fournir une instance du type. .NET fournit deux implémentations IFormatProvider pour la mise en forme des nombres :

Si une implémentation IFormatProvider n’est pas fournie explicitement à une méthode de mise en forme, un objet CultureInfo retourné par la propriété CultureInfo.CurrentCulture qui représente la culture actuelle est utilisé.

L’exemple suivant illustre la relation entre l’interface IFormatProvider et la classe NumberFormatInfo dans des opérations de mise en forme en définissant une implémentation IFormatProvider personnalisée. Sa méthode GetFormat affiche le nom de type de l’objet demandé par l’opération de mise en forme. Si l’interface demande un objet NumberFormatInfo, cette méthode fournit l’objet NumberFormatInfo de la culture actuelle. Comme le montre la sortie de l’exemple, la méthode Decimal.ToString(IFormatProvider) demande à un objet NumberFormatInfo de fournir des informations de mise en forme, tandis que la méthode String.Format(IFormatProvider, String, Object[]) demande des objets NumberFormatInfo et DateTimeFormatInfo, ainsi qu’une implémentation 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

Si une implémentation IFormatProvider n’est pas explicitement fournie dans un appel de méthode de mise en forme numérique, la méthode appelle la méthode CultureInfo.CurrentCulture.GetFormat retournant l’objet NumberFormatInfo qui correspond à la culture actuelle.

Chaînes de format et propriétés NumberFormatInfo

Chaque opération de mise en forme utilise une chaîne de format numérique standard ou personnalisée pour produire une chaîne de résultats à partir d’un nombre. L’utilisation d’une chaîne de format pour produire une chaîne de résultats est parfois explicite, comme dans l’exemple suivant. Ce code appelle la méthode Decimal.ToString(IFormatProvider) pour convertir une valeur Decimal en plusieurs représentations de chaîne différentes en utilisant des conventions de mise en forme de la culture 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

Dans d’autres cas, l’utilisation d’une chaîne de format est implicite. Par exemple, dans les appels de méthode suivants à la méthode Decimal.ToString() sans paramètre ou par défaut, la valeur de l’instance Decimal est mise en forme en tirant parti du spécificateur de format général (« G ») et des conventions de la culture actuelle, qui dans ce cas est la culture 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

Chaque chaîne de format numérique standard utilise une ou plusieurs propriétés NumberFormatInfo pour déterminer le modèle ou les symboles utilisés dans la chaîne de résultats. De la même manière, chaque spécificateur de format numérique personnalisé sauf « 0 » et « # » insère des symboles dans la chaîne de résultats qui sont définis par des propriétés NumberFormatInfo. Le tableau suivant répertorie les spécificateurs de format numérique standard et personnalisés, ainsi que leurs propriétés NumberFormatInfo associées. Pour modifier l’apparence de la chaîne de résultats pour une culture particulière, consultez la section Modifier les propriétés NumberFormatInfo. Pour obtenir plus d’informations sur l’utilisation de ces spécificateurs de format, consultez Chaînes de format numériques standard et Chaînes de format numériques personnalisées.

Spécificateur de format Propriétés associées
« C » ou « c » (spécificateur de format monétaire) CurrencyDecimalDigits, pour définir le nombre par défaut de chiffres fractionnaires.

CurrencyDecimalSeparator, pour définir le symbole de séparateur décimal.

CurrencyGroupSeparator, pour définir le groupe ou le séparateur de milliers.

CurrencyGroupSizes, pour définir les tailles des groupes intégraux.

CurrencyNegativePattern, pour définir le modèle de valeurs monétaires négatives.

CurrencyPositivePattern, pour définir le modèle de valeurs monétaires positives.

CurrencySymbol, pour définir le symbole monétaire.

NegativeSign, pour définir le symbole de signe négatif.
« D » ou « d » (spécificateur de format décimal) NegativeSign, pour définir le symbole de signe négatif.
« E » ou « e » (spécificateur de format exponentiel ou scientifique) NegativeSign, pour définir le symbole de signe négatif dans la mantisse et l’exposant.

NumberDecimalSeparator, pour définir le symbole de séparateur décimal.

PositiveSign, pour définir le symbole de signe positif dans l’exposant.
« F » ou « f » (spécificateur de format à virgule fixe) NegativeSign, pour définir le symbole de signe négatif.

NumberDecimalDigits, pour définir le nombre par défaut de chiffres fractionnaires.

NumberDecimalSeparator, pour définir le symbole de séparateur décimal.
« G » ou « g » (spécificateur de format général) NegativeSign, pour définir le symbole de signe négatif.

NumberDecimalSeparator, pour définir le symbole de séparateur décimal.

PositiveSign, pour définir le symbole de signe positif pour des chaînes de résultats au format exponentiel.
« N » ou « n » (spécificateur de format de nombre) NegativeSign, pour définir le symbole de signe négatif.

NumberDecimalDigits, pour définir le nombre par défaut de chiffres fractionnaires.

NumberDecimalSeparator, pour définir le symbole de séparateur décimal.

NumberGroupSeparator, pour définir le symbole du séparateur de groupes (milliers).

NumberGroupSizes, pour définir le nombre de chiffres intégraux d’un groupe.

NumberNegativePattern, pour définir le format de valeurs négatives.
« P » ou « p » (spécificateur de format de pourcentage) NegativeSign, pour définir le symbole de signe négatif.

PercentDecimalDigits, pour définir le nombre par défaut de chiffres fractionnaires.

PercentDecimalSeparator, pour définir le symbole de séparateur décimal.

PercentGroupSeparator, pour définir le symbole de séparateur de groupes.

PercentGroupSizes, pour définir le nombre de chiffres intégraux d’un groupe.

PercentNegativePattern, pour définir la position du symbole de pourcentage et le symbole négatif pour les valeurs négatives.

PercentPositivePattern, pour définir la position du symbole de pourcentage pour des valeurs positives.

PercentSymbol, pour définir le symbole de pourcentage.
« R » ou « r » (spécificateur de format aller-retour) NegativeSign, pour définir le symbole de signe négatif.

NumberDecimalSeparator, pour définir le symbole de séparateur décimal.

PositiveSign, pour définir le symbole de signe positif dans un exposant.
« X » ou « x » (spécificateur de format hexadécimal) Aucune
« . » (spécificateur de format personnalisé de virgule décimale) NumberDecimalSeparator, pour définir le symbole de séparateur décimal.
« , » (spécificateur de format personnalisé de séparateur de groupes) NumberGroupSeparator, pour définir le symbole de séparateur de groupes (milliers).
« % » (spécificateur de format personnalisé d’espace réservé de pourcentage) PercentSymbol, pour définir le symbole de pourcentage.
« ‰ » (spécificateur de format personnalisé d’espace réservé de milliers) PerMilleSymbol, pour définir le symbole par millier.
« E » (spécificateur de format personnalisé de notation exponentielle) NegativeSign, pour définir le symbole de signe négatif dans la mantisse et l’exposant.

PositiveSign, pour définir le symbole de signe positif dans l’exposant.

Notez que la classe NumberFormatInfo comprend une propriété NativeDigits qui spécifie les 10 chiffres de base utilisés par une culture spécifique. Toutefois, la propriété n’est pas utilisée dans des opérations de mise en forme ; seuls les chiffres latins de base 0 (U+0030) à 9 (U+0039) sont utilisés dans la chaîne de résultats. En outre, pour les valeurs Single et Double de NaN, PositiveInfinity et NegativeInfinity, la chaîne de résultats se compose exclusivement des symboles définis par les propriétés NaNSymbol, PositiveInfinitySymbol et NegativeInfinitySymbol, respectivement.

Modifier les propriétés NumberFormatInfo

Vous pouvez modifier les propriétés d’un objet NumberFormatInfo pour personnaliser la chaîne de résultats produite dans une opération de mise en forme numérique. Pour ce faire :

  1. Créez une copie en lecture/écriture d’un objet NumberFormatInfo dont vous souhaitez modifier les conventions de mise en forme. Pour obtenir plus d’informations, consultez la section Instancier un objet NumberFormatInfo.

  2. Modifiez la ou les propriétés utilisées pour produire la chaîne de résultats souhaitée. Si vous souhaitez obtenir plus d’informations sur la façon dont les méthodes de mise en forme utilisent des propriétés NumberFormatInfo pour définir des chaînes de résultats, consultez la section Chaînes de format et propriétés NumberFormatInfo.

  3. Utilisez l’objet NumberFormatInfo personnalisé comme argument IFormatProvider dans des appels aux méthodes de mise en forme.

Remarque

Au lieu de modifier dynamiquement les valeurs de propriété d’une culture chaque fois qu’une application est démarrée, vous pouvez utiliser la classe CultureAndRegionInfoBuilder pour définir une culture personnalisée (culture ayant un nom unique et qui complète des cultures existantes) ou une culture de remplacement (une culture qui est utilisée au lieu d’une culture spécifique).

Les sections suivantes offrent quelques exemples.

Modifier le modèle et le symbole monétaire

L’exemple suivant modifie un objet NumberFormatInfo qui représente les conventions de mise en forme de la culture en-US. Il affecte le symbole de devise ISO-4217 à la propriété CurrencySymbol et définit un modèle pour les valeurs monétaires qui se compose du symbole monétaire suivi d’un espace et d’une valeur numérique.

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

Mettre en forme un numéro d’identification national

De nombreux numéros d’identification nationaux se composent exclusivement de chiffres et peuvent donc être facilement mis en forme en modifiant les propriétés d’un objet NumberFormatInfo. Par exemple, un numéro de sécurité sociale aux États-Unis se compose de 9 chiffres organisés comme suit : XXX-XX-XXXX. L’exemple suivant suppose que les numéros de sécurité sociale sont stockés sous forme de valeurs entières et les met en forme de manière appropriée.

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

Analyser des chaînes numériques

L’analyse implique la conversion de la représentation sous forme de chaîne d’un nombre en nombre. Chaque type numérique dans .NET comprend deux méthodes d’analyse surchargées : Parse et TryParse. La méthode Parse convertit une chaîne en nombre et lève une exception en cas d’échec de la conversion. La méthode TryParse convertit une chaîne en nombre, attribue le nombre à un argument out et retourne une valeur Boolean qui indique la réussite ou non de la conversion.

Les méthodes d’analyse utilisent implicitement ou explicitement une valeur d’énumération NumberStyles pour déterminer les éléments de style (tels que les séparateurs de groupes, un séparateur décimal ou un symbole monétaire) qui peuvent être présents dans une chaîne pour assurer la réussite de l’opération d’analyse. Si aucune valeur NumberStyles n’est fournie dans l’appel de méthode, la valeur par défaut est une valeur NumberStyles qui inclut les indicateurs Float et AllowThousands permettant de spécifier que la chaîne analysée peut inclure des symboles de groupe, un séparateur décimal, un signe négatif et des espaces blancs. Il peut également s’agir de la représentation sous forme de chaîne d’un nombre en notation exponentielle.

Les méthodes d’analyse utilisent également implicitement ou explicitement un objet NumberFormatInfo qui définit les symboles et les modèles spécifiques qui peuvent se produire dans la chaîne à analyser. Si un objet NumberFormatInfo n’est pas fourni, la valeur par défaut est NumberFormatInfo pour la culture actuelle. Si vous souhaitez obtenir plus d’informations sur l’analyse, consultez les méthodes d’analyse individuelles, telles que Int16.Parse(String), Int32.Parse(String, NumberStyles), Int64.Parse(String, IFormatProvider), Decimal.Parse(String, NumberStyles, IFormatProvider), Double.TryParse(String, Double) et BigInteger.TryParse(String, NumberStyles, IFormatProvider, BigInteger).

L’exemple suivant montre la nature sensible à la culture des chaînes d’analyse. Il tente d’analyser une chaîne qui inclut des séparateurs de milliers en utilisant les conventions des cultures en-US, fr-FR et des cultures invariantes. Une chaîne qui comprend la virgule comme séparateur de groupes et le point comme séparateur décimal ne parvient pas à être analysée dans la culture fr-FR et une chaîne avec un espace blanc comme séparateur de groupes et une virgule comme séparateur décimal ne parvient pas à être analysée dans les cultures invariantes et 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)

L’analyse se produit généralement dans deux contextes :

  • En tant qu’opération conçue pour convertir une entrée utilisateur en valeur numérique.

  • En tant qu’opération conçue pour effectuer un aller-retour d’une valeur numérique ; autrement dit, pour désérialiser une valeur numérique précédemment sérialisée comme chaîne.

Les sections suivantes décrivent ces deux opérations de façon plus détaillée.

Analyser des chaînes d’utilisateurs

Lorsque vous analysez des chaînes numériques entrées par l’utilisateur, vous devez toujours instancier un objet NumberFormatInfo qui reflète les paramètres culturels de l’utilisateur. Si vous souhaitez obtenir plus d’informations sur l’instanciation d’un objet NumberFormatInfo qui reflète les personnalisations des utilisateurs, consultez la section Données dynamiques.

L’exemple suivant montre la différence entre une opération d’analyse qui reflète les paramètres culturels d’un utilisateur et une autre qui ne le fait pas. Dans ce cas, la culture système par défaut est en-US, mais l’utilisateur a défini « , » comme symbole décimal et « . » comme séparateur de groupes dans le Panneau de configuration, Région et langue. En règle générale, ces symboles sont inversés dans la culture en-US par défaut. Lorsque l’utilisateur entre une chaîne qui reflète les paramètres utilisateur et que la chaîne est analysée par un objet NumberFormatInfo qui reflète également les paramètres utilisateur (remplacements), l’opération d’analyse retourne un résultat correct. Cependant, lorsque la chaîne est analysée par un objet NumberFormatInfo qui reflète des paramètres culturels standard en-US, elle confond le symbole de virgule avec un séparateur de groupes et retourne un résultat incorrect.

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

Sérialiser et désérialiser des données numériques

Lorsque des données numériques sont sérialisées au format de chaîne, puis désérialisées et analysées plus tard, les chaînes doivent être générées et analysées en utilisant les conventions de la culture invariante. Les opérations de mise en forme et d’analyse ne doivent jamais refléter les conventions d’une culture spécifique. Si les paramètres spécifiques à la culture sont utilisés, la portabilité des données est strictement limitée ; elles peuvent être correctement désérialisées uniquement sur un thread dont les paramètres spécifiques à la culture sont identiques à ceux du thread sur lequel elles ont été sérialisées. Dans certains cas, cela signifie que les données ne peuvent même pas être correctement désérialisées sur le même système que celui sur lequel elles ont été sérialisées.

L’exemple suivant montre ce qui peut se produire lorsque ce principe est violé. Les valeurs à virgule flottante d’un tableau sont converties en chaînes lorsque le thread actuel utilise les paramètres spécifiques à la culture de la culture en-US. Les données sont ensuite analysées par un thread qui utilise les paramètres spécifiques à la culture de la culture pt-BR. Dans ce cas, bien que chaque opération d’analyse réussisse, les données n’effectuent pas un aller-retour correct et une altération des données se produit. Dans d’autres cas, une opération d’analyse peut échouer et une exception FormatException peut être levée.

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