Classe NumberFormatInfo

Questo articolo fornisce osservazioni supplementari alla documentazione di riferimento per questa API.

La NumberFormatInfo classe contiene informazioni specifiche delle impostazioni cultura usate quando si formattano e si analizzano i valori numerici. Queste informazioni includono il simbolo di valuta, il simbolo decimale, il simbolo separatore di gruppo e i simboli per segni positivi e negativi.

Creare un'istanza di un oggetto NumberFormatInfo

È possibile creare un'istanza di un NumberFormatInfo oggetto che rappresenta le convenzioni di formattazione delle impostazioni cultura correnti, le impostazioni cultura invarianti, le impostazioni cultura specifiche o le impostazioni cultura neutre.

Creare un'istanza di un oggetto NumberFormatInfo per le impostazioni cultura correnti

È possibile creare un'istanza di un NumberFormatInfo oggetto per le impostazioni cultura correnti in uno dei modi seguenti. In ogni caso, l'oggetto restituito NumberFormatInfo è di sola lettura.

Nell'esempio seguente vengono usati questi tre modi per creare NumberFormatInfo oggetti che rappresentano le convenzioni di formattazione delle impostazioni cultura correnti. Recupera inoltre il valore della IsReadOnly proprietà per illustrare che ogni oggetto è di sola lettura.

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

È possibile creare un oggetto scrivibile NumberFormatInfo che rappresenta le convenzioni delle impostazioni cultura correnti in uno dei modi seguenti:

Nell'esempio seguente vengono illustrati questi due modi per creare un'istanza di un NumberFormatInfo oggetto e viene visualizzato il valore della relativa IsReadOnly proprietà per illustrare che l'oggetto non è di sola lettura.

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

Si noti che il sistema operativo Windows consente all'utente di eseguire l'override di alcuni dei valori delle NumberFormatInfo proprietà usati nelle operazioni di formattazione e analisi numeriche tramite l'elemento Region and Language in Pannello di controllo. Ad esempio, un utente con impostazioni cultura inglese (Stati Uniti) potrebbe scegliere di visualizzare i valori di valuta come 1,1 USD anziché il valore predefinito di $1,1. Gli NumberFormatInfo oggetti recuperati nei modi descritti in precedenza riflettono tutte queste sostituzioni utente. Se ciò non è indesiderato, è possibile creare un NumberFormatInfo oggetto che non rifletta le sostituzioni utente (e che sia anche di lettura/scrittura anziché di sola lettura) chiamando il CultureInfo.CultureInfo(String, Boolean) costruttore e fornendo un valore di false per l'argomento useUserOverride . Nell'esempio seguente viene fornita un'illustrazione di un sistema le cui impostazioni cultura correnti sono inglese (Stati Uniti) e il cui simbolo di valuta è stato modificato dal valore predefinito di $ a 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: $

Se la CultureInfo.UseUserOverride proprietà è impostata su true, le proprietà CultureInfo.DateTimeFormat, CultureInfo.NumberFormate CultureInfo.TextInfo vengono recuperate anche dalle impostazioni utente. Se le impostazioni utente non sono compatibili con le impostazioni cultura associate all'oggetto CultureInfo , ad esempio se il calendario selezionato non è uno dei calendari elencati dalla OptionalCalendars proprietà , i risultati dei metodi e i valori delle proprietà non sono definiti.

Creare un'istanza di un oggetto NumberFormatInfo per le impostazioni cultura invarianti

Le impostazioni cultura invarianti rappresentano impostazioni cultura senza distinzione tra impostazioni cultura. Si basa sulla lingua inglese, ma non su uno specifico paese/area geografica in lingua inglese. Anche se i dati di impostazioni cultura specifiche possono essere dinamici e possono cambiare per riflettere nuove convenzioni culturali o preferenze utente, i dati delle impostazioni cultura invarianti non cambiano. Un NumberFormatInfo oggetto che rappresenta le convenzioni di formattazione delle impostazioni cultura invarianti può essere utilizzato per le operazioni di formattazione in cui le stringhe di risultato non devono variare in base alle impostazioni cultura.

È possibile creare un'istanza di un NumberFormatInfo oggetto che rappresenta le convenzioni di formattazione delle impostazioni cultura invarianti nei modi seguenti:

Nell'esempio seguente vengono usati ognuno di questi metodi per creare un'istanza di un NumberFormatInfo oggetto che rappresenta le impostazioni cultura invarianti. Indica quindi se l'oggetto è di sola lettura,

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

Creare un'istanza di un oggetto NumberFormatInfo per impostazioni cultura specifiche

Una cultura specifica rappresenta una lingua parlata in un determinato paese/area geografica. Ad esempio, en-US è una cultura specifica che rappresenta la lingua inglese parlata nel Stati Uniti e en-CA è una cultura specifica che rappresenta la lingua inglese parlata in Canada. È possibile creare un'istanza di un NumberFormatInfo oggetto che rappresenta le convenzioni di formattazione di impostazioni cultura specifiche nei modi seguenti:

L'esempio seguente usa questi quattro modi per creare un NumberFormatInfo oggetto che riflette le convenzioni di formattazione delle impostazioni cultura indonesiane (Indonesia). Indica anche se ogni oggetto è di sola lettura.

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

Creare un'istanza di un oggetto NumberFormatInfo per impostazioni cultura neutre

Una cultura neutra rappresenta una lingua o una cultura indipendente da un paese o un'area geografica. In genere è l'elemento padre di una o più impostazioni cultura specifiche. Ad esempio, fr è una cultura neutra per la lingua francese e l'elemento padre delle impostazioni cultura fr-FR. Si crea un NumberFormatInfo oggetto che rappresenta le convenzioni di formattazione di impostazioni cultura neutre nello stesso modo in cui si crea un NumberFormatInfo oggetto che rappresenta le convenzioni di formattazione di impostazioni cultura specifiche.

Tuttavia, poiché è indipendente da un paese/area geografica specifica, una cultura neutra non dispone di informazioni di formattazione specifiche delle impostazioni cultura. Anziché popolare l'oggetto NumberFormatInfo con valori generici, .NET restituisce un NumberFormatInfo oggetto che riflette le convenzioni di formattazione di impostazioni cultura specifiche figlio delle impostazioni cultura neutre. Ad esempio, l'oggetto NumberFormatInfo per le impostazioni cultura en neutral riflette le convenzioni di formattazione delle impostazioni cultura en-US e l'oggetto NumberFormatInfo per le impostazioni cultura fr riflette le convenzioni di formattazione delle impostazioni cultura fr-FR.

È possibile usare codice simile al seguente per determinare le convenzioni di formattazione delle impostazioni cultura specifiche rappresentate da ogni cultura neutra.

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

Dati dinamici

I dati specifici delle impostazioni cultura per la NumberFormatInfo formattazione dei valori numerici forniti dalla classe sono dinamici, esattamente come i dati culturali forniti dalla CultureInfo classe . Non è consigliabile fare ipotesi sulla stabilità dei valori per NumberFormatInfo gli oggetti associati a oggetti specifici CultureInfo . Solo i dati forniti dalle impostazioni cultura invarianti e il relativo oggetto associato NumberFormatInfo sono stabili. Altri dati possono cambiare tra le sessioni dell'applicazione o anche all'interno di una singola sessione, per i motivi seguenti:

  • Aggiornamenti del sistema. Le preferenze culturali, ad esempio il simbolo di valuta o i formati di valuta, cambiano nel tempo. In questo caso, Windows Update include modifiche al valore della NumberFormatInfo proprietà per impostazioni cultura specifiche.

  • Impostazioni cultura di sostituzione. La CultureAndRegionInfoBuilder classe può essere usata per sostituire i dati di impostazioni cultura esistenti.

  • Modifiche a catena ai valori delle proprietà. Una serie di proprietà correlate alle impostazioni cultura può cambiare in fase di esecuzione, che, a sua volta, causa la modifica dei NumberFormatInfo dati. Ad esempio, le impostazioni cultura correnti possono essere modificate a livello di codice o tramite l'azione dell'utente. In questo caso, l'oggetto NumberFormatInfo restituito dalla CurrentInfo proprietà passa a un oggetto associato alle impostazioni cultura correnti.

  • Preferenze utente. Gli utenti dell'applicazione potrebbero eseguire l'override di alcuni dei valori associati alle impostazioni cultura di sistema correnti tramite le opzioni di area geografica e lingua in Pannello di controllo. Ad esempio, gli utenti potrebbero scegliere un simbolo di valuta diverso o un simbolo separatore decimale diverso. Se la CultureInfo.UseUserOverride proprietà è impostata su true (valore predefinito), le proprietà dell'oggetto NumberFormatInfo vengono recuperate anche dalle impostazioni utente.

Tutte le proprietà sovrascrivibili dall'utente di un NumberFormatInfo oggetto vengono inizializzate al momento della creazione dell'oggetto. Esiste ancora una possibilità di incoerenza, perché non è atomica né la creazione di oggetti né il processo di override dell'utente e i valori rilevanti possono cambiare durante la creazione dell'oggetto. Tuttavia, queste incoerenze dovrebbero essere estremamente rare.

È possibile controllare se le sostituzioni utente vengono riflesse negli NumberFormatInfo oggetti che rappresentano le stesse impostazioni cultura delle impostazioni cultura correnti. Nella tabella seguente sono elencati i modi in cui è possibile recuperare un NumberFormatInfo oggetto e indica se l'oggetto risultante riflette gli override dell'utente.

Origine dell'oggetto CultureInfo e NumberFormatInfo Riflette le sostituzioni utente
Proprietà CultureInfo.CurrentCulture.NumberFormat
Proprietà NumberFormatInfo.CurrentInfo
Metodo CultureInfo.CreateSpecificCulture
Metodo CultureInfo.GetCultureInfo No
Costruttore CultureInfo(String)
Costruttore CultureInfo.CultureInfo(String, Boolean) Dipende dal valore del useUserOverride parametro

A meno che non esista un motivo interessante per eseguire altre operazioni, è consigliabile rispettare le sostituzioni dell'utente quando si usa l'oggetto NumberFormatInfo nelle applicazioni client per formattare e analizzare l'input dell'utente o per visualizzare i dati numerici. Per le applicazioni server o le applicazioni automatiche, non è consigliabile rispettare le sostituzioni utente. Tuttavia, se si usa l'oggetto NumberFormatInfo in modo esplicito o implicito per rendere persistenti i dati numerici in formato stringa, è consigliabile utilizzare un NumberFormatInfo oggetto che rifletta le convenzioni di formattazione delle impostazioni cultura invarianti oppure specificare una stringa di formato numerico personalizzata usata indipendentemente dalle impostazioni cultura.

IFormatProvider, NumberFormatInfo e formattazione numerica

Un NumberFormatInfo oggetto viene utilizzato in modo implicito o esplicito in tutte le operazioni di formattazione numerica. Queste includono chiamate ai metodi seguenti:

Tutte le operazioni di formattazione numerica usano un'implementazione IFormatProvider . L'interfaccia IFormatProvider include un singolo metodo, GetFormat(Type). Si tratta di un metodo di callback che viene passato a un Type oggetto che rappresenta il tipo necessario per fornire informazioni di formattazione. Il metodo è responsabile della restituzione di un'istanza di tale tipo o null, se non è in grado di fornire un'istanza del tipo. .NET offre due IFormatProvider implementazioni per la formattazione dei numeri:

Se non viene fornita un'implementazione IFormatProvider a un metodo di formattazione in modo esplicito, viene utilizzato un CultureInfo oggetto restituito dalla CultureInfo.CurrentCulture proprietà che rappresenta le impostazioni cultura correnti.

Nell'esempio seguente viene illustrata la relazione tra l'interfaccia IFormatProvider e la NumberFormatInfo classe nelle operazioni di formattazione definendo un'implementazione personalizzata IFormatProvider . Il GetFormat metodo visualizza il nome del tipo dell'oggetto richiesto dall'operazione di formattazione. Se l'interfaccia richiede un NumberFormatInfo oggetto , questo metodo fornisce l'oggetto NumberFormatInfo per le impostazioni cultura correnti. Come illustrato nell'output dell'esempio, il Decimal.ToString(IFormatProvider) metodo richiede a un NumberFormatInfo oggetto di fornire informazioni di formattazione, mentre il String.Format(IFormatProvider, String, Object[]) metodo richiede NumberFormatInfo e DateTimeFormatInfo oggetti nonché un'implementazione 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

Se un'implementazione IFormatProvider non viene specificata in modo esplicito in una chiamata al metodo di formattazione numerica, il metodo chiama il CultureInfo.CurrentCulture.GetFormat metodo , che restituisce l'oggetto NumberFormatInfo corrispondente alle impostazioni cultura correnti.

Stringhe di formato e proprietà NumberFormatInfo

Ogni operazione di formattazione usa una stringa di formato numerico standard o personalizzata per produrre una stringa di risultato da un numero. In alcuni casi, l'uso di una stringa di formato per produrre una stringa di risultato è esplicito, come nell'esempio seguente. Questo codice chiama il Decimal.ToString(IFormatProvider) metodo per convertire un Decimal valore in diverse rappresentazioni di stringa usando le convenzioni di formattazione delle impostazioni cultura 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

In altri casi, l'uso di una stringa di formato è implicito. Nel metodo seguente, ad esempio, chiama il metodo predefinito o senza Decimal.ToString() parametri, il valore dell'istanza Decimal viene formattato usando l'identificatore di formato generale ("G") e le convenzioni delle impostazioni cultura correnti, che in questo caso sono le impostazioni cultura 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

Ogni stringa di formato numerico standard usa una o più NumberFormatInfo proprietà per determinare il criterio o i simboli usati nella stringa di risultato. Analogamente, ogni identificatore di formato numerico personalizzato, ad eccezione di "0" e "#" inserisce i simboli nella stringa di risultato definita dalle NumberFormatInfo proprietà. Nella tabella seguente sono elencati gli identificatori di formato numerico standard e personalizzato e le relative proprietà associate NumberFormatInfo . Per modificare l'aspetto della stringa di risultato per impostazioni cultura specifiche, vedere la sezione Modificare le proprietà NumberFormatInfo. Per informazioni dettagliate sull'uso di questi identificatori di formato, vedere Stringhe di formato numerico standard e stringhe di formato numerico personalizzato.

Identificatore di formato Proprietà associate
"C" o "c" (identificatore di formato valuta) CurrencyDecimalDigitsper definire il numero predefinito di cifre frazionarie.

CurrencyDecimalSeparator, per definire il simbolo di separatore decimale.

CurrencyGroupSeparatorper definire il separatore di gruppi o migliaia.

CurrencyGroupSizes, per definire le dimensioni dei gruppi integrali.

CurrencyNegativePattern, per definire il modello di valori di valuta negativi.

CurrencyPositivePatternper definire il modello di valori di valuta positivi.

CurrencySymbolper definire il simbolo di valuta.

NegativeSign, per definire il simbolo di segno negativo.
"D" o "d" (identificatore di formato decimale) NegativeSign, per definire il simbolo di segno negativo.
"E" o "e" (identificatore di formato esponenziale o scientifico) NegativeSignper definire il simbolo di segno negativo nella mantissa e nell'esponente.

NumberDecimalSeparator, per definire il simbolo di separatore decimale.

PositiveSignper definire il simbolo di segno positivo nell'esponente.
"F" o "f" (identificatore di formato a virgola fissa) NegativeSign, per definire il simbolo di segno negativo.

NumberDecimalDigitsper definire il numero predefinito di cifre frazionarie.

NumberDecimalSeparator, per definire il simbolo di separatore decimale.
"G" o "g" (identificatore di formato generale) NegativeSign, per definire il simbolo di segno negativo.

NumberDecimalSeparator, per definire il simbolo di separatore decimale.

PositiveSign, per definire il simbolo del segno positivo per le stringhe di risultato in formato esponenziale.
"N" o "n" (identificatore di formato numerico) NegativeSign, per definire il simbolo di segno negativo.

NumberDecimalDigitsper definire il numero predefinito di cifre frazionarie.

NumberDecimalSeparator, per definire il simbolo di separatore decimale.

NumberGroupSeparatorper definire il simbolo separatore di gruppo (migliaia).

NumberGroupSizesper definire il numero di cifre integrali in un gruppo.

NumberNegativePatternper definire il formato dei valori negativi.
"P" o "p" (identificatore di formato percentuale) NegativeSign, per definire il simbolo di segno negativo.

PercentDecimalDigitsper definire il numero predefinito di cifre frazionarie.

PercentDecimalSeparator, per definire il simbolo di separatore decimale.

PercentGroupSeparatorper definire il simbolo separatore di gruppo.

PercentGroupSizesper definire il numero di cifre integrali in un gruppo.

PercentNegativePattern, per definire la posizione del simbolo di percentuale e il simbolo negativo per i valori negativi.

PercentPositivePattern, per definire la posizione del simbolo di percentuale per i valori positivi.

PercentSymbol, per definire il simbolo di percentuale.
"R" o "r" (identificatore di formato round trip) NegativeSign, per definire il simbolo di segno negativo.

NumberDecimalSeparator, per definire il simbolo di separatore decimale.

PositiveSignper definire il simbolo di segno positivo in un esponente.
"X" o "x" (identificatore di formato esadecimale) Nessuno.
"." (identificatore di formato personalizzato in virgola decimale) NumberDecimalSeparator, per definire il simbolo di separatore decimale.
"," (identificatore di formato personalizzato separatore di gruppo) NumberGroupSeparatorper definire il simbolo separatore di gruppo (migliaia).
"%" (identificatore di formato personalizzato segnaposto percentuale) PercentSymbol, per definire il simbolo di percentuale.
"*" (identificatore di formato personalizzato segnaposto per mille) PerMilleSymbol, per definire il simbolo per mille.
"E" (identificatore di formato personalizzato di notazione esponenziale) NegativeSignper definire il simbolo di segno negativo nella mantissa e nell'esponente.

PositiveSignper definire il simbolo di segno positivo nell'esponente.

Si noti che la NumberFormatInfo classe include una NativeDigits proprietà che specifica le 10 cifre di base utilizzate da impostazioni cultura specifiche. Tuttavia, la proprietà non viene utilizzata nelle operazioni di formattazione; nella stringa di risultato vengono usate solo le cifre latine di base da 0 (U+0030) a 9 (U+0039). Inoltre, per Single i valori e Double di NaN, PositiveInfinitye NegativeInfinity, la stringa di risultato è costituita esclusivamente dai simboli definiti rispettivamente dalle NaNSymbolproprietà , PositiveInfinitySymbole NegativeInfinitySymbol .

Modificare le proprietà NumberFormatInfo

È possibile modificare le proprietà di un NumberFormatInfo oggetto per personalizzare la stringa di risultato prodotta in un'operazione di formattazione numerica. A questo scopo:

  1. Creare una copia di lettura/scrittura di un NumberFormatInfo oggetto le cui convenzioni di formattazione si desidera modificare. Per altre informazioni, vedere la sezione Creare un'istanza di un oggetto NumberFormatInfo.

  2. Modificare la proprietà o le proprietà utilizzate per produrre la stringa di risultato desiderata. Per informazioni su come i metodi di formattazione usano NumberFormatInfo le proprietà per definire le stringhe di risultato, vedere la sezione Stringhe di formato e proprietà NumberFormatInfo.

  3. Utilizzare l'oggetto personalizzato NumberFormatInfo come IFormatProvider argomento nelle chiamate ai metodi di formattazione.

Nota

Anziché modificare dinamicamente i valori delle proprietà di una cultura ogni volta che viene avviata un'applicazione, è possibile usare la CultureAndRegionInfoBuilder classe per definire impostazioni cultura personalizzate (impostazioni cultura con un nome univoco e che integrano le impostazioni cultura esistenti) o impostazioni cultura di sostituzione (una usata invece di impostazioni cultura specifiche).

Le sezioni seguenti forniscono alcuni esempi.

Modificare il simbolo e il criterio di valuta

Nell'esempio seguente viene modificato un NumberFormatInfo oggetto che rappresenta le convenzioni di formattazione delle impostazioni cultura en-US. Assegna il simbolo di valuta ISO-4217 alla CurrencySymbol proprietà e definisce un modello per i valori di valuta costituiti dal simbolo di valuta seguito da uno spazio e da un valore numerico.

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

Formattare un numero di identificazione nazionale

Molti numeri di identificazione nazionali sono costituiti esclusivamente da cifre e quindi possono essere facilmente formattati modificando le proprietà di un NumberFormatInfo oggetto. Ad esempio, un numero di previdenza sociale nel Stati Uniti è costituito da 9 cifre disposte nel modo seguente: XXX-XX-XXXX. Nell'esempio seguente si presuppone che i numeri di previdenza sociale vengano archiviati come valori interi e li formatta in modo appropriato.

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

Analizzare stringhe numeriche

L'analisi comporta la conversione della rappresentazione di stringa di un numero in un numero. Ogni tipo numerico in .NET include due metodi di analisi di overload: Parse e TryParse. Il Parse metodo converte una stringa in un numero e genera un'eccezione se la conversione non riesce. Il TryParse metodo converte una stringa in un numero, assegna il numero a un out argomento e restituisce un Boolean valore che indica se la conversione è riuscita.

I metodi di analisi usano in modo implicito o esplicito un NumberStyles valore di enumerazione per determinare quali elementi di stile (ad esempio separatori di gruppo, separatori decimali o simbolo di valuta) possono essere presenti in una stringa se l'operazione di analisi deve avere esito positivo. Se un NumberStyles valore non viene specificato nella chiamata al metodo, il valore predefinito è un NumberStyles valore che include i Float flag e AllowThousands , che specifica che la stringa analizzata può includere simboli di gruppo, un separatore decimale, un segno negativo e spazi vuoti oppure può essere la rappresentazione di stringa di un numero in notazione esponenziale.

I metodi di analisi usano anche in modo implicito o esplicito un NumberFormatInfo oggetto che definisce i simboli e i modelli specifici che possono verificarsi nella stringa da analizzare. Se non viene specificato un NumberFormatInfo oggetto, il valore predefinito è per NumberFormatInfo le impostazioni cultura correnti. Per altre informazioni sull'analisi, vedere i singoli metodi di analisi, ad esempio Int16.Parse(String), Int32.Parse(String, NumberStyles)Double.TryParse(String, Double)Int64.Parse(String, IFormatProvider)Decimal.Parse(String, NumberStyles, IFormatProvider)e .BigInteger.TryParse(String, NumberStyles, IFormatProvider, BigInteger)

Nell'esempio seguente viene illustrata la natura sensibile alle impostazioni cultura delle stringhe di analisi. Tenta di analizzare una stringa che include migliaia di separatori usando le convenzioni delle impostazioni cultura en-US, fr-FR e invarianti. Una stringa che include la virgola come separatore di gruppo e il punto come separatore decimale non riesce ad analizzare nelle impostazioni cultura fr-FR e una stringa con spazi vuoti come separatore di gruppo e una virgola come separatore decimale non riesce ad analizzare nelle impostazioni cultura en-US e invarianti.

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'analisi si verifica in genere in due contesti:

  • Come operazione progettata per convertire l'input dell'utente in un valore numerico.

  • Come operazione progettata per eseguire il round trip di un valore numerico; ovvero per deserializzare un valore numerico serializzato in precedenza come stringa.

Le sezioni seguenti illustrano in modo più dettagliato queste due operazioni.

Analizzare le stringhe utente

Quando si analizzano le stringhe numeriche immesse dall'utente, è consigliabile creare sempre un'istanza di un NumberFormatInfo oggetto che rifletta le impostazioni cultura dell'utente. Per informazioni su come creare un'istanza di un NumberFormatInfo oggetto che riflette le personalizzazioni utente, vedere la sezione Dati dinamici.

Nell'esempio seguente viene illustrata la differenza tra un'operazione di analisi che riflette le impostazioni cultura dell'utente e una che non lo fa. In questo caso, le impostazioni cultura di sistema predefinite sono en-US, ma l'utente ha definito "," come simbolo decimale e "." come separatore di gruppo in Pannello di controllo, area e lingua. In genere, questi simboli vengono invertiti nelle impostazioni cultura predefinite en-US. Quando l'utente immette una stringa che riflette le impostazioni utente e la stringa viene analizzata da un NumberFormatInfo oggetto che riflette anche le impostazioni utente (sostituzioni), l'operazione di analisi restituisce un risultato corretto. Tuttavia, quando la stringa viene analizzata da un NumberFormatInfo oggetto che riflette le impostazioni cultura standard en-US, si sbaglia il simbolo virgola per un separatore di gruppo e restituisce un risultato non corretto.

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

Serializzare e deserializzare i dati numerici

Quando i dati numerici vengono serializzati in formato stringa e successivamente deserializzati e analizzati, le stringhe devono essere generate e analizzate usando le convenzioni delle impostazioni cultura invarianti. Le operazioni di formattazione e analisi non devono mai riflettere le convenzioni di impostazioni cultura specifiche. Se vengono usate impostazioni specifiche delle impostazioni cultura, la portabilità dei dati è strettamente limitata; può essere deserializzato correttamente solo in un thread le cui impostazioni specifiche delle impostazioni cultura sono identiche a quelle del thread in cui è stato serializzato. In alcuni casi, ciò significa che i dati non possono essere deserializzati correttamente nello stesso sistema in cui è stato serializzato.

L'esempio seguente illustra cosa può accadere quando questo principio viene violato. I valori a virgola mobile in una matrice vengono convertiti in stringhe quando il thread corrente usa le impostazioni specifiche delle impostazioni cultura delle impostazioni cultura en-US. I dati vengono quindi analizzati da un thread che usa le impostazioni specifiche delle impostazioni cultura delle impostazioni cultura pt-BR. In questo caso, anche se ogni operazione di analisi ha esito positivo, i dati non vengono completati correttamente e si verifica un danneggiamento dei dati. In altri casi, un'operazione di analisi potrebbe non riuscire e potrebbe essere generata un'eccezione 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