Panoramica: Come formattare numeri, date, enumerazioni e altri tipi in .NET

La formattazione è il processo di conversione di un'istanza di una classe, di una struttura o di un valore di enumerazione in una rappresentazione di stringa. Lo scopo è visualizzare la stringa risultante agli utenti o di deserializzarla in un secondo momento per ripristinare il tipo di dati originale. Questo articolo presenta i meccanismi di formattazione forniti da .NET.

Nota

mentre l'analisi è l'operazione inversa. Un'operazione di analisi consente di creare un'istanza di un tipo di dati dalla relativa rappresentazione di stringa. Per altre informazioni, vedere Analisi delle stringhe. Per altre informazioni su serializzazione e deserializzazione, vedere Serializzazione in .NET.

Il meccanismo di base per la formattazione è costituito dall'implementazione predefinita del metodo Object.ToString, illustrato nella sezione Formattazione predefinita tramite il metodo ToString più avanti in questo argomento. In .NET sono tuttavia disponibili diversi metodi per modificare ed estendere il supporto predefinito della formattazione, Di seguito sono elencate le quattro opzioni disponibili.

  • Override del metodo Object.ToString per definire una rappresentazione di stringa personalizzata del valore di un oggetto. Per altre informazioni, vedere la sezione Override del metodo ToString più avanti in questo argomento.

  • Definizione di identificatori di formato che consentono l'assunzione di più forme da parte della rappresentazione di stringa del valore di un oggetto. L'identificatore di formato "X" nell'istruzione seguente consente, ad esempio, di convertire un valore intero nella rappresentazione di stringa di un valore esadecimale.

    int integerValue = 60312;
    Console.WriteLine(integerValue.ToString("X"));   // Displays EB98.
    
    Dim integerValue As Integer = 60312
    Console.WriteLine(integerValue.ToString("X"))   ' Displays EB98.
    

    Per altre informazioni sugli identificatori di formato, vedere la sezione Metodo ToString e stringhe di formato .

  • Uso di provider di formato per implementare le convenzioni di formattazione di impostazioni cultura specifiche. Nell'istruzione seguente, ad esempio, viene visualizzato un valore di valuta usando le convenzioni di formattazione delle impostazioni cultura en-US.

    double cost = 1632.54;
    Console.WriteLine(cost.ToString("C",
                      new System.Globalization.CultureInfo("en-US")));
    // The example displays the following output:
    //       $1,632.54
    
    Dim cost As Double = 1632.54
    Console.WriteLine(cost.ToString("C", New System.Globalization.CultureInfo("en-US")))
    ' The example displays the following output:
    '       $1,632.54
    

    Per altre informazioni sulla formattazione con i provider di formato, vedere la sezione Provider di formato.

  • Implementazione dell'interfaccia IFormattable per supportare sia la conversione di stringa con la classe Convert che la formattazione composita. Per altre informazioni, vedere la sezione Interfaccia IFormattable .

  • Uso della formattazione composita per incorporare la rappresentazione di stringa di un valore in una stringa di dimensioni maggiori. Per altre informazioni, vedere la sezione Formattazione composita .

  • Uso dell'interpolazione di stringhe, una sintassi più leggibile per incorporare la rappresentazione di stringa di un valore in una stringa più grande. Per altre informazioni, vedere Interpolazione di stringhe.

  • Implementazione di ICustomFormatter e IFormatProvider per fornire una soluzione di formattazione personalizzata completa. Per altre informazioni, vedere la sezione Formattazione personalizzata con ICustomFormatter .

Nelle sezioni seguenti vengono esaminati questi metodi per la conversione di un oggetto nella relativa rappresentazione di stringa.

Formattazione predefinita tramite il metodo ToString

Ogni tipo derivato da System.Object eredita automaticamente un metodo ToString senza parametri che, per impostazione predefinita, restituisce il nome del tipo. Nell'esempio seguente viene illustrato il metodo ToString predefinito. Viene definita una classe denominata Automobile che non dispone di implementazione. Quando viene creata un'istanza della classe e viene chiamato il relativo metodo ToString , viene visualizzato il nome del tipo relativo. Si noti che il metodo ToString non viene chiamato in modo esplicito nell'esempio. Il metodo Console.WriteLine(Object) chiama in modo implicito il metodo ToString dell'oggetto passato come argomento.

using System;

public class Automobile
{
   // No implementation. All members are inherited from Object.
}

public class Example9
{
   public static void Main()
   {
      Automobile firstAuto = new Automobile();
      Console.WriteLine(firstAuto);
   }
}
// The example displays the following output:
//       Automobile
Public Class Automobile
    ' No implementation. All members are inherited from Object.
End Class

Module Example9
    Public Sub Main9()
        Dim firstAuto As New Automobile()
        Console.WriteLine(firstAuto)
    End Sub
End Module
' The example displays the following output:
'       Automobile

Avviso

A partire da Windows 8.1, Windows Runtime include un'interfaccia IStringable con un singolo metodo, IStringable.ToString, che fornisce supporto per la formattazione predefinita. È tuttavia consigliabile che i tipi gestiti non implementino l'interfaccia IStringable . Per altre informazioni, vedere la sezione "Windows Runtime e l'interfaccia IStringable" nella pagina di riferimento Object.ToString.

Poiché tutti i tipi diversi dalle interfacce sono derivati da Object, questa funzionalità viene fornita automaticamente alle classi o alle strutture personalizzate. La funzionalità offerta dal metodo ToString predefinito è tuttavia limitata poiché non fornisce informazioni su un'istanza del tipo sebbene consenta di identificarlo. Per fornire una rappresentazione di stringa di un oggetto che fornisce informazioni su tale oggetto, è necessario eseguire l'override del metodo ToString .

Nota

Le strutture ereditano dall'oggetto ValueType, che a sua volta viene derivato da Object. Sebbene ValueType esegua l'override di Object.ToString, l'implementazione è identica.

Eseguire l'override del metodo ToString

La visualizzazione del nome di un tipo ha spesso un uso limitato e non consente agli utenti dei tipi di distinguere tra le istanze. È tuttavia possibile eseguire l'override del metodo ToString per fornire una rappresentazione più utile del valore di un oggetto. Nell'esempio seguente viene definito un oggetto Temperature e viene eseguito l'override del relativo metodo ToString per visualizzare la temperatura in gradi Celsius.

public class Temperature
{
    private decimal temp;

    public Temperature(decimal temperature)
    {
        this.temp = temperature;
    }

    public override string ToString()
    {
        return this.temp.ToString("N1") + "°C";
    }
}

public class Example12
{
    public static void Main()
    {
        Temperature currentTemperature = new Temperature(23.6m);
        Console.WriteLine($"The current temperature is {currentTemperature}");
    }
}
// The example displays the following output:
//       The current temperature is 23.6°C.
Public Class Temperature
    Private temp As Decimal

    Public Sub New(temperature As Decimal)
        Me.temp = temperature
    End Sub

    Public Overrides Function ToString() As String
        Return Me.temp.ToString("N1") + "°C"
    End Function
End Class

Module Example13
    Public Sub Main13()
        Dim currentTemperature As New Temperature(23.6D)
        Console.WriteLine("The current temperature is " +
                          currentTemperature.ToString())
    End Sub
End Module
' The example displays the following output:
'       The current temperature is 23.6°C.

In .NET è stato eseguito l'override del metodo ToString di ogni tipo di valore primitivo per visualizzare il valore dell'oggetto invece del nome. Nella tabella seguente viene illustrato l'override per ogni tipo primitivo. Si noti che la maggior parte dei metodi sottoposti a override chiama un altro overload del metodo ToString e passa a esso l'identificatore di formato "G", che definisce il formato generale per il tipo, e un oggetto IFormatProvider , che rappresenta le impostazioni cultura correnti.

Type Override di ToString
Boolean Restituisce Boolean.TrueString o Boolean.FalseString.
Byte Chiama Byte.ToString("G", NumberFormatInfo.CurrentInfo) per formattare il valore Byte per le impostazioni cultura correnti.
Char Restituisce il carattere come stringa.
DateTime Chiama DateTime.ToString("G", DatetimeFormatInfo.CurrentInfo) per formattare il valore di data e ora per le impostazioni cultura correnti.
Decimal Chiama Decimal.ToString("G", NumberFormatInfo.CurrentInfo) per formattare il valore Decimal per le impostazioni cultura correnti.
Double Chiama Double.ToString("G", NumberFormatInfo.CurrentInfo) per formattare il valore Double per le impostazioni cultura correnti.
Int16 Chiama Int16.ToString("G", NumberFormatInfo.CurrentInfo) per formattare il valore Int16 per le impostazioni cultura correnti.
Int32 Chiama Int32.ToString("G", NumberFormatInfo.CurrentInfo) per formattare il valore Int32 per le impostazioni cultura correnti.
Int64 Chiama Int64.ToString("G", NumberFormatInfo.CurrentInfo) per formattare il valore Int64 per le impostazioni cultura correnti.
SByte Chiama SByte.ToString("G", NumberFormatInfo.CurrentInfo) per formattare il valore SByte per le impostazioni cultura correnti.
Single Chiama Single.ToString("G", NumberFormatInfo.CurrentInfo) per formattare il valore Single per le impostazioni cultura correnti.
UInt16 Chiama UInt16.ToString("G", NumberFormatInfo.CurrentInfo) per formattare il valore UInt16 per le impostazioni cultura correnti.
UInt32 Chiama UInt32.ToString("G", NumberFormatInfo.CurrentInfo) per formattare il valore UInt32 per le impostazioni cultura correnti.
UInt64 Chiama UInt64.ToString("G", NumberFormatInfo.CurrentInfo) per formattare il valore UInt64 per le impostazioni cultura correnti.

Metodo ToString e stringhe di formato

L'utilizzo del metodo ToString predefinito o l'esecuzione dell'override di ToString è un'operazione appropriata quando un oggetto dispone di una singola rappresentazione di stringa. Spesso, tuttavia, il valore di un oggetto dispone di più rappresentazioni. È ad esempio possibile esprimere una temperatura in gradi Fahrenheit, gradi Celsius o gradi Kelvin. Analogamente, il valore intero 10 può essere rappresentato in diversi modi, tra cui 10, 10,0, 1.0e01 o €10,00.

Per consentire a un singolo valore di disporre di più rappresentazioni di stringa, in .NET vengono usate le stringhe di formato. Una stringa di formato è una stringa che contiene uno o più identificatori di formato predefiniti costituiti da singoli caratteri o gruppi di caratteri che definiscono il modo in cui deve essere formattato l'output del metodo ToString . La stringa di formato viene quindi passata come parametro al metodo ToString dell'oggetto per determinare come deve venire visualizzata la rappresentazione di stringa del valore di tale oggetto.

Tutti i tipi numerici, di data e ora e di enumerazione in .NET supportano un set predefinito di identificatori di formato. È anche possibile usare le stringhe di formato per definire più rappresentazioni di stringa dei tipi di dati definiti dall'applicazione.

Stringhe di formato standard

Una stringa di formato standard contiene un singolo identificatore di formato, che è un carattere alfabetico che definisce la rappresentazione di stringa dell'oggetto a cui viene applicata, insieme a un identificatore di precisione facoltativo, che influisce sul numero di cifre visualizzate nella stringa di risultato. Se l'identificatore di precisione viene omesso o non è supportato, un identificatore di formato standard è equivalente a una stringa di formato standard.

In .NET viene definito un set di identificatori di formato standard per tutti i tipi numerici, di data e ora e di enumerazione. Ognuna di queste categorie supporta, ad esempio, un identificatore di formato standard "G", che definisce una rappresentazione di stringa generale di un valore di tale tipo.

Le stringhe di formato standard per i tipi di enumerazione controllano direttamente la rappresentazione di stringa di un valore. Le stringhe di formato passate al metodo ToString del valore di un'enumerazione determinano se il valore viene visualizzato tramite il relativo nome di stringa (identificatori di formato "G" e "F"), il relativo valore integrale sottostante (identificatore di formato "D") oppure il relativo valore esadecimale (identificatore di formato "X"). Nell'esempio seguente viene illustrato l'uso delle stringhe di formato standard per formattare un valore dell'enumerazione DayOfWeek .

DayOfWeek thisDay = DayOfWeek.Monday;
string[] formatStrings = {"G", "F", "D", "X"};

foreach (string formatString in formatStrings)
   Console.WriteLine(thisDay.ToString(formatString));
// The example displays the following output:
//       Monday
//       Monday
//       1
//       00000001
Dim thisDay As DayOfWeek = DayOfWeek.Monday
Dim formatStrings() As String = {"G", "F", "D", "X"}

For Each formatString As String In formatStrings
    Console.WriteLine(thisDay.ToString(formatString))
Next
' The example displays the following output:
'       Monday
'       Monday
'       1
'       00000001

Per informazioni sulle stringhe del formato di enumerazione, vedere Enumeration Format Strings.

Le stringhe di formato standard per i tipi numerici definiscono in genere una stringa di risultato il cui aspetto preciso viene controllato da uno o più valori delle proprietà. L'identificatore di formato "C", ad esempio, consente di formattare un numero come valore di valuta. Quando si chiama il metodo ToString con l'identificatore di formato "C" come unico parametro, vengono usati i valori delle proprietà seguenti dell'oggetto NumberFormatInfo delle impostazioni cultura correnti per definire la rappresentazione di stringa del valore numerico:

  • La proprietà CurrencySymbol, che specifica il simbolo di valuta delle impostazioni cultura correnti.

  • Proprietà CurrencyNegativePattern o CurrencyPositivePattern , che restituisce un valore intero che determina gli aspetti seguenti:

    • Posizione del simbolo di valuta.

    • Utilizzo di un segno negativo iniziale, di un segno negativo finale o di parentesi per indicare i valori negativi.

    • Inserimento di uno spazio tra il valore numerico e il simbolo di valuta.

  • Proprietà CurrencyDecimalDigits , che definisce il numero di cifre frazionarie nella stringa di risultato.

  • Proprietà CurrencyDecimalSeparator , che definisce il simbolo del separatore decimale nella stringa di risultato.

  • Proprietà CurrencyGroupSeparator , che definisce il simbolo del separatore di gruppi.

  • Proprietà CurrencyGroupSizes , che definisce il numero di cifre in ogni gruppo a sinistra del separatore decimale.

  • Proprietà NegativeSign , che determina il segno negativo usato nella stringa di risultato se non vengono usate parentesi per indicare i valori negativi.

Le stringhe di formato numerico possono inoltre includere un identificatore di precisione. Il significato di questo identificatore dipende dalla stringa di formato con la quale viene usato, ma in genere esso indica il numero totale di cifre o il numero di cifre frazionarie che devono essere presenti nella stringa di risultato. Nell'esempio seguente vengono usati, ad esempio, la stringa numerica standard "X4"e un identificatore di precisione per creare un valore stringa con quattro cifre esadecimali.

byte[] byteValues = { 12, 163, 255 };
foreach (byte byteValue in byteValues)
   Console.WriteLine(byteValue.ToString("X4"));
// The example displays the following output:
//       000C
//       00A3
//       00FF
Dim byteValues() As Byte = {12, 163, 255}
For Each byteValue As Byte In byteValues
    Console.WriteLine(byteValue.ToString("X4"))
Next
' The example displays the following output:
'       000C
'       00A3
'       00FF

Per altre informazioni sulle stringhe di formattazione numerica standard, vedere Standard Numeric Format Strings.

Le stringhe di formato standard per i valori di data e ora sono alias per stringhe di formato personalizzate archiviate da una proprietà DateTimeFormatInfo specifica. Se viene chiamato, ad esempio, il metodo ToString di un valore di data e ora con l'identificatore di formato "D", la data e l'ora vengono visualizzate usando la stringa di formato personalizzata archiviata nella proprietà DateTimeFormatInfo.LongDatePattern delle impostazioni cultura correnti. Per altre informazioni sulle stringhe di formato personalizzate, vedere la sezione successiva. Nell'esempio seguente viene illustrata questa relazione.

using System;
using System.Globalization;

public class Example
{
   public static void Main()
   {
      DateTime date1 = new DateTime(2009, 6, 30);
      Console.WriteLine("D Format Specifier:     {0:D}", date1);
      string longPattern = CultureInfo.CurrentCulture.DateTimeFormat.LongDatePattern;
      Console.WriteLine("'{0}' custom format string:     {1}",
                        longPattern, date1.ToString(longPattern));
   }
}
// The example displays the following output when run on a system whose
// current culture is en-US:
//    D Format Specifier:     Tuesday, June 30, 2009
//    'dddd, MMMM dd, yyyy' custom format string:     Tuesday, June 30, 2009
Imports System.Globalization

Module Example
    Public Sub Main0()
        Dim date1 As Date = #6/30/2009#
        Console.WriteLine("D Format Specifier:     {0:D}", date1)
        Dim longPattern As String = CultureInfo.CurrentCulture.DateTimeFormat.LongDatePattern
        Console.WriteLine("'{0}' custom format string:     {1}",
                          longPattern, date1.ToString(longPattern))
    End Sub
End Module
' The example displays the following output when run on a system whose
' current culture is en-US:
'    D Format Specifier:     Tuesday, June 30, 2009
'    'dddd, MMMM dd, yyyy' custom format string:     Tuesday, June 30, 2009

Per altre informazioni sulle stringhe di formato di data e ora standard, vedere Standard Date and Time Format Strings.

È anche possibile usare le stringhe di formato standard per definire la rappresentazione di stringa di un oggetto definito dall'applicazione, prodotta dal metodo ToString(String) dell'oggetto. È possibile definire gli identificatori di formato standard specifici supportati dall'oggetto, nonché determinare se per essi viene fatta o meno distinzione tra maiuscole e minuscole. L'implementazione del metodo ToString(String) deve supportare gli elementi seguenti:

  • Un identificatore di formato "G" che rappresenta un formato abituale o comune dell'oggetto. L'overload senza parametri del metodo ToString dell'oggetto deve chiamare il relativo overload di ToString(String) e passare a esso la stringa di formato standard "G".

  • Supporto per un identificatore di formato equivalente a un riferimento Null (Nothing in Visual Basic). Un identificatore di formato equivalente a un riferimento Null deve essere considerato equivalente all'identificatore di formato "G".

Una classe Temperature può, ad esempio, archiviare internamente la temperatura in gradi Celsius e usare gli identificatori di formato per rappresentare il valore dell'oggetto Temperature in gradi Celsius, gradi Fahrenheit e gradi Kelvin. Di seguito ne viene illustrato un esempio.

using System;

public class Temperature
{
   private decimal m_Temp;

   public Temperature(decimal temperature)
   {
      this.m_Temp = temperature;
   }

   public decimal Celsius
   {
      get { return this.m_Temp; }
   }

   public decimal Kelvin
   {
      get { return this.m_Temp + 273.15m; }
   }

   public decimal Fahrenheit
   {
      get { return Math.Round(((decimal) (this.m_Temp * 9 / 5 + 32)), 2); }
   }

   public override string ToString()
   {
      return this.ToString("C");
   }

   public string ToString(string format)
   {
      // Handle null or empty string.
      if (String.IsNullOrEmpty(format)) format = "C";
      // Remove spaces and convert to uppercase.
      format = format.Trim().ToUpperInvariant();

      // Convert temperature to Fahrenheit and return string.
      switch (format)
      {
         // Convert temperature to Fahrenheit and return string.
         case "F":
            return this.Fahrenheit.ToString("N2") + " °F";
         // Convert temperature to Kelvin and return string.
         case "K":
            return this.Kelvin.ToString("N2") + " K";
         // return temperature in Celsius.
         case "G":
         case "C":
            return this.Celsius.ToString("N2") + " °C";
         default:
            throw new FormatException(String.Format("The '{0}' format string is not supported.", format));
      }
   }
}

public class Example1
{
   public static void Main()
   {
      Temperature temp1 = new Temperature(0m);
      Console.WriteLine(temp1.ToString());
      Console.WriteLine(temp1.ToString("G"));
      Console.WriteLine(temp1.ToString("C"));
      Console.WriteLine(temp1.ToString("F"));
      Console.WriteLine(temp1.ToString("K"));

      Temperature temp2 = new Temperature(-40m);
      Console.WriteLine(temp2.ToString());
      Console.WriteLine(temp2.ToString("G"));
      Console.WriteLine(temp2.ToString("C"));
      Console.WriteLine(temp2.ToString("F"));
      Console.WriteLine(temp2.ToString("K"));

      Temperature temp3 = new Temperature(16m);
      Console.WriteLine(temp3.ToString());
      Console.WriteLine(temp3.ToString("G"));
      Console.WriteLine(temp3.ToString("C"));
      Console.WriteLine(temp3.ToString("F"));
      Console.WriteLine(temp3.ToString("K"));

      Console.WriteLine(String.Format("The temperature is now {0:F}.", temp3));
   }
}
// The example displays the following output:
//       0.00 °C
//       0.00 °C
//       0.00 °C
//       32.00 °F
//       273.15 K
//       -40.00 °C
//       -40.00 °C
//       -40.00 °C
//       -40.00 °F
//       233.15 K
//       16.00 °C
//       16.00 °C
//       16.00 °C
//       60.80 °F
//       289.15 K
//       The temperature is now 16.00 °C.
Public Class Temperature
    Private m_Temp As Decimal

    Public Sub New(temperature As Decimal)
        Me.m_Temp = temperature
    End Sub

    Public ReadOnly Property Celsius() As Decimal
        Get
            Return Me.m_Temp
        End Get
    End Property

    Public ReadOnly Property Kelvin() As Decimal
        Get
            Return Me.m_Temp + 273.15D
        End Get
    End Property

    Public ReadOnly Property Fahrenheit() As Decimal
        Get
            Return Math.Round(CDec(Me.m_Temp * 9 / 5 + 32), 2)
        End Get
    End Property

    Public Overrides Function ToString() As String
        Return Me.ToString("C")
    End Function

    Public Overloads Function ToString(format As String) As String
        ' Handle null or empty string.
        If String.IsNullOrEmpty(format) Then format = "C"
        ' Remove spaces and convert to uppercase.
        format = format.Trim().ToUpperInvariant()

        Select Case format
            Case "F"
                ' Convert temperature to Fahrenheit and return string.
                Return Me.Fahrenheit.ToString("N2") & " °F"
            Case "K"
                ' Convert temperature to Kelvin and return string.
                Return Me.Kelvin.ToString("N2") & " K"
            Case "C", "G"
                ' Return temperature in Celsius.
                Return Me.Celsius.ToString("N2") & " °C"
            Case Else
                Throw New FormatException(String.Format("The '{0}' format string is not supported.", format))
        End Select
    End Function
End Class

Public Module Example1
    Public Sub Main1()
        Dim temp1 As New Temperature(0D)
        Console.WriteLine(temp1.ToString())
        Console.WriteLine(temp1.ToString("G"))
        Console.WriteLine(temp1.ToString("C"))
        Console.WriteLine(temp1.ToString("F"))
        Console.WriteLine(temp1.ToString("K"))

        Dim temp2 As New Temperature(-40D)
        Console.WriteLine(temp2.ToString())
        Console.WriteLine(temp2.ToString("G"))
        Console.WriteLine(temp2.ToString("C"))
        Console.WriteLine(temp2.ToString("F"))
        Console.WriteLine(temp2.ToString("K"))

        Dim temp3 As New Temperature(16D)
        Console.WriteLine(temp3.ToString())
        Console.WriteLine(temp3.ToString("G"))
        Console.WriteLine(temp3.ToString("C"))
        Console.WriteLine(temp3.ToString("F"))
        Console.WriteLine(temp3.ToString("K"))

        Console.WriteLine(String.Format("The temperature is now {0:F}.", temp3))
    End Sub
End Module
' The example displays the following output:
'       0.00 °C
'       0.00 °C
'       0.00 °C
'       32.00 °F
'       273.15 K
'       -40.00 °C
'       -40.00 °C
'       -40.00 °C
'       -40.00 °F
'       233.15 K
'       16.00 °C
'       16.00 °C
'       16.00 °C
'       60.80 °F
'       289.15 K
'       The temperature is now 16.00 °C.

Stringhe di formato personalizzate

Oltre alle stringhe di formato standard, in .NET sono definite stringhe di formato personalizzate sia per valori numerici che per valori di data e ora. Una stringa di formato personalizzata è costituita da uno o più identificatori di formato personalizzati che definiscono la rappresentazione di stringa di un valore. La stringa di formato di data e ora personalizzata "yyyy/mm/dd hh:mm:ss.ffff t zzz" consente, ad esempio, di convertire una data nella relativa rappresentazione di stringa nel formato "2008/11/15 07:45:00.0000 P -08:00" per le impostazioni cultura en-US. Analogamente, la stringa di formato personalizzata "0000" consente di convertire il valore intero 12 in "0012". Per un elenco completo di stringhe di formato personalizzate, vedere Custom Date and Time Format Strings e Custom Numeric Format Strings.

Se una stringa di formato è costituita da un solo identificatore di formato personalizzato, l'identificatore di formato deve essere preceduto dal simbolo di percentuale (%) per evitare confusione con un identificatore di formato standard. Nell'esempio seguente viene usato l'identificatore di formato personalizzato "M" per visualizzare un numero a una cifra o a due cifre del mese di una data specifica.

DateTime date1 = new DateTime(2009, 9, 8);
Console.WriteLine(date1.ToString("%M"));       // Displays 9
Dim date1 As Date = #09/08/2009#
Console.WriteLine(date1.ToString("%M"))      ' Displays 9

Numerose stringhe di formato standard per i valori di data e ora sono alias per stringhe di formato personalizzate definite dalle proprietà dell'oggetto DateTimeFormatInfo . Le stringhe di formato personalizzate offrono inoltre una notevole flessibilità in quanto consentono una formattazione definita dall'applicazione per valori numerici o di data e ora. È possibile definire stringhe di risultato personalizzate sia per valori numerici che per valori di data e ora combinando più identificatori di formato personalizzati in una singola stringa di formato personalizzata. Nell'esempio seguente viene definita una stringa di formato personalizzata che consente di visualizzare il giorno della settimana tra parentesi dopo il nome del mese, il giorno e l'anno.

string customFormat = "MMMM dd, yyyy (dddd)";
DateTime date1 = new DateTime(2009, 8, 28);
Console.WriteLine(date1.ToString(customFormat));
// The example displays the following output if run on a system
// whose language is English:
//       August 28, 2009 (Friday)
Dim customFormat As String = "MMMM dd, yyyy (dddd)"
Dim date1 As Date = #8/28/2009#
Console.WriteLine(date1.ToString(customFormat))
' The example displays the following output if run on a system
' whose language is English:
'       August 28, 2009 (Friday)      

L'esempio seguente definisce una stringa di formato personalizzata che visualizza un valore Int64 come numero di telefono degli Stati Uniti standard di sette cifre con il relativo prefisso.

using System;

public class Example17
{
   public static void Main()
   {
      long number = 8009999999;
      string fmt = "000-000-0000";
      Console.WriteLine(number.ToString(fmt));
   }
}
// The example displays the following output:
//        800-999-9999
Module Example18
    Public Sub Main18()
        Dim number As Long = 8009999999
        Dim fmt As String = "000-000-0000"
        Console.WriteLine(number.ToString(fmt))
    End Sub
End Module
' The example displays the following output:

' The example displays the following output:
'       800-999-9999

Sebbene le stringhe di formato standard consentano in genere di gestire la maggior parte delle necessità relative alla formattazione per i tipi definiti dall'applicazione, è anche possibile definire identificatori di formato personalizzati per formattare i tipi.

Stringhe di formato e tipi .NET

Tutti i tipi numerici (ovvero i tipi Byte, Decimal, Double, Int16, Int32, Int64, SByte, Single, UInt16, UInt32, UInt64 e BigInteger), nonché DateTime, DateTimeOffset, TimeSpan, Guid e tutti i tipi di enumerazione supportano la formattazione con stringhe di formato. Per informazioni sulle stringhe di formato specifiche supportate da ogni tipo, vedere gli argomenti seguenti:

Title Definizione
Stringhe di formato numerico standard Vengono descritte le stringhe di formato standard che consentono di creare rappresentazioni di stringa usate comunemente di valori numerici.
Stringhe di formato numerico personalizzato Vengono descritte le stringhe di formato personalizzate che consentono di creare formati specifici dell'applicazione per valori numerici.
Stringhe formato data e ora standard Vengono descritte le stringhe di formato standard che consentono di creare rappresentazioni di stringa usate comunemente di valori DateTime e DateTimeOffset.
Stringhe formato data e ora personalizzate Vengono descritte le stringhe di formato personalizzate che consentono di creare formati specifici dell'applicazione per valori DateTime e DateTimeOffset.
Stringhe di formato TimeSpan standard Vengono descritte le stringhe di formato standard che consentono di creare rappresentazioni di stringa usate comunemente di intervalli di tempo.
Stringhe di formato TimeSpan personalizzate Vengono descritte le stringhe di formato personalizzate che consentono di creare formati specifici dell'applicazione per intervalli di tempo.
Enumeration Format Strings Vengono descritte le stringhe di formato standard che consentono di creare rappresentazioni di stringa di valori di enumerazione.
Guid.ToString(String) Descrive le stringhe di formato standard per i valori Guid .

Formattazione sensibile alle impostazioni cultura con provider di formato

Sebbene gli identificatori di formato consentano di personalizzare la formattazione degli oggetti, la creazione di una rappresentazione di stringa significativa degli oggetti richiede spesso informazioni aggiuntive sulla formattazione. La formattazione, ad esempio, di un numero come valore di valuta tramite la stringa di formato standard "C" o una stringa di formato personalizzata, come ad esempio "$ #,#.00", richiede almeno la possibilità di includere nella stringa formattata le informazioni relative al simbolo di valuta, al separatore di gruppi e al separatore decimale corretti. In .NET queste informazioni aggiuntive sulla formattazione vengono rese disponibili tramite l'interfaccia IFormatProvider, fornita come parametro di uno o più overload del metodo ToString di tipi numerici e di data e ora. Le implementazioni di IFormatProvider vengono usate in .NET per supportare la formattazione specifica delle impostazioni cultura. Nell'esempio seguente viene illustrato come cambia la rappresentazione di stringa di un oggetto quando viene formattata con tre oggetti IFormatProvider che rappresentano impostazioni cultura diverse.

using System;
using System.Globalization;

public class Example18
{
   public static void Main()
   {
      decimal value = 1603.42m;
      Console.WriteLine(value.ToString("C3", new CultureInfo("en-US")));
      Console.WriteLine(value.ToString("C3", new CultureInfo("fr-FR")));
      Console.WriteLine(value.ToString("C3", new CultureInfo("de-DE")));
   }
}
// The example displays the following output:
//       $1,603.420
//       1 603,420 €
//       1.603,420 €
Imports System.Globalization

Public Module Example11
    Public Sub Main11()
        Dim value As Decimal = 1603.42D
        Console.WriteLine(value.ToString("C3", New CultureInfo("en-US")))
        Console.WriteLine(value.ToString("C3", New CultureInfo("fr-FR")))
        Console.WriteLine(value.ToString("C3", New CultureInfo("de-DE")))
    End Sub
End Module
' The example displays the following output:
'       $1,603.420
'       1 603,420 €
'       1.603,420 €

L'interfaccia IFormatProvider include un metodo, GetFormat(Type), che dispone di un singolo parametro che specifica il tipo di oggetto che fornisce informazioni sulla formattazione. Se il metodo può fornire un oggetto di tale tipo, lo restituisce. In caso contrario, restituisce un riferimento Null (Nothing in Visual Basic).

IFormatProvider.GetFormat è un metodo di callback. Quando si chiama un overload del metodo ToString che include un parametro IFormatProvider , viene chiamato il metodo GetFormat di tale oggetto IFormatProvider . Il metodo GetFormat è responsabile della restituzione di un oggetto che fornisce le informazioni sulla formattazione necessarie, specificate dal relativo parametro formatType , al metodo ToString .

Diversi metodi di conversione di stringhe o di formattazione includono un parametro di tipo IFormatProvider, ma in molti casi il valore del parametro viene ignorato quando il metodo viene chiamato. Nella tabella seguente sono elencati alcuni dei metodi di formattazione che usano il parametro e il tipo dell'oggetto Type che passano al metodo IFormatProvider.GetFormat .

metodo Tipo di parametro formatType
Metodo ToString di tipi numerici System.Globalization.NumberFormatInfo
Metodo ToString di tipi di data e ora System.Globalization.DateTimeFormatInfo
String.Format System.ICustomFormatter
StringBuilder.AppendFormat System.ICustomFormatter

Nota

I metodi ToString dei tipi numerici e di data e ora sono sottoposti a overload e solo alcuni degli overload includono un parametro IFormatProvider . Se un metodo non dispone di un parametro di tipo IFormatProvider, al suo posto viene passato l'oggetto restituito dalla proprietà CultureInfo.CurrentCulture . Una chiamata al metodo Int32.ToString() predefinito comporta, ad esempio, in definitiva, una chiamata al metodo come la seguente: Int32.ToString("G", System.Globalization.CultureInfo.CurrentCulture).

In .NET sono disponibili tre classi che implementano IFormatProvider:

  • DateTimeFormatInfo, una classe che fornisce informazioni sulla formattazione per i valori di data e ora per impostazioni cultura specifiche. L'implementazione del metodo IFormatProvider.GetFormat della classe restituisce un'istanza della classe stessa.

  • NumberFormatInfo, una classe che fornisce informazioni sulla formattazione numerica per impostazioni cultura specifiche. L'implementazione del metodo IFormatProvider.GetFormat della classe restituisce un'istanza della classe stessa.

  • CultureInfo. L'implementazione del metodo IFormatProvider.GetFormat della classe può restituire un oggetto NumberFormatInfo per fornire informazioni sulla formattazione numerica o un oggetto DateTimeFormatInfo per fornire informazioni sulla formattazione per i valori di data e ora.

È anche possibile implementare un provider di formato personalizzato per sostituire una di queste classi. Il metodo GetFormat dell'implementazione, tuttavia, deve restituire un oggetto del tipo elencato nella tabella precedente, se deve fornire informazioni sulla formattazione al metodo ToString.

Formattazione dipendente dalle impostazioni cultura di valori numerici

Per impostazione predefinita, la formattazione di valori numerici è dipendente dalle impostazioni cultura. Se non si specificano impostazioni cultura quando si chiama un metodo di formattazione, vengono usate le convenzioni di formattazione delle impostazioni cultura correnti. Questa situazione viene illustrata nell'esempio seguente in cui le impostazioni cultura correnti vengono cambiate quattro volte e viene chiamato il metodo Decimal.ToString(String). In ogni caso, la stringa risultante riflette le convenzioni di formattazione delle impostazioni cultura correnti. Questo accade perché i metodi ToString e ToString(String) eseguono il wrapping di chiamate al metodo ToString(String, IFormatProvider) di ogni tipo numerico.

using System.Globalization;

public class Example6
{
   public static void Main()
   {
      string[] cultureNames = { "en-US", "fr-FR", "es-MX", "de-DE" };
      Decimal value = 1043.17m;

      foreach (var cultureName in cultureNames) {
         // Change the current culture.
         CultureInfo.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureName);
         Console.WriteLine($"The current culture is {CultureInfo.CurrentCulture.Name}");
         Console.WriteLine(value.ToString("C2"));
         Console.WriteLine();
      }
   }
}
// The example displays the following output:
//       The current culture is en-US
//       $1,043.17
//
//       The current culture is fr-FR
//       1 043,17 €
//
//       The current culture is es-MX
//       $1,043.17
//
//       The current culture is de-DE
//       1.043,17 €
Imports System.Globalization

Module Example6
    Public Sub Main6()
        Dim cultureNames() As String = {"en-US", "fr-FR", "es-MX", "de-DE"}
        Dim value As Decimal = 1043.17D

        For Each cultureName In cultureNames
            ' Change the current culture.
            CultureInfo.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureName)
            Console.WriteLine($"The current culture is {CultureInfo.CurrentCulture.Name}")
            Console.WriteLine(value.ToString("C2"))
            Console.WriteLine()
        Next
    End Sub
End Module
' The example displays the following output:
'       The current culture is en-US
'       $1,043.17
'       
'       The current culture is fr-FR
'       1 043,17 €
'       
'       The current culture is es-MX
'       $1,043.17
'       
'       The current culture is de-DE
'       1.043,17 €

È anche possibile formattare un valore numerico per impostazioni cultura specifiche chiamando un overload di ToString con un parametro provider e passando uno degli elementi seguenti:

  • Oggetto CultureInfo che rappresenta le impostazioni cultura, di cui verranno usate le convenzioni di formattazione. Il metodo CultureInfo.GetFormat relativo restituisce il valore della proprietà CultureInfo.NumberFormat , che rappresenta l'oggetto NumberFormatInfo che fornisce informazioni di formattazione specifiche delle impostazioni cultura per i valori numerici.

  • Oggetto NumberFormatInfo che definisce le convenzioni di formattazione specifiche delle impostazioni cultura da usare. Il metodo GetFormat relativo restituisce un'istanza di se stesso.

Nell'esempio seguente vengono usati gli oggetti NumberFormatInfo che rappresentano le impostazioni cultura della lingua Inglese (Stati Uniti) e Inglese (Regno Unito), nonché le impostazioni cultura non associate alle lingue francese e russa per formattare un numero a virgola mobile.

using System.Globalization;

public class Example7
{
    public static void Main()
    {
        double value = 1043.62957;
        string[] cultureNames = { "en-US", "en-GB", "ru", "fr" };

        foreach (string? name in cultureNames)
        {
            NumberFormatInfo nfi = CultureInfo.CreateSpecificCulture(name).NumberFormat;
            Console.WriteLine("{0,-6} {1}", name + ":", value.ToString("N3", nfi));
        }
    }
}
// The example displays the following output:
//       en-US: 1,043.630
//       en-GB: 1,043.630
//       ru:    1 043,630
//       fr:    1 043,630
Imports System.Globalization

Module Example7
    Public Sub Main7()
        Dim value As Double = 1043.62957
        Dim cultureNames() As String = {"en-US", "en-GB", "ru", "fr"}

        For Each name In cultureNames
            Dim nfi As NumberFormatInfo = CultureInfo.CreateSpecificCulture(name).NumberFormat
            Console.WriteLine("{0,-6} {1}", name + ":", value.ToString("N3", nfi))
        Next
    End Sub
End Module
' The example displays the following output:
'       en-US: 1,043.630
'       en-GB: 1,043.630
'       ru:    1 043,630
'       fr:    1 043,630

Formattazione dipendente dalle impostazioni cultura di valori data e ora

Per impostazione predefinita, la formattazione dei valori data e ora è dipendente dalle impostazioni cultura. Se non si specificano impostazioni cultura quando si chiama un metodo di formattazione, vengono usate le convenzioni di formattazione delle impostazioni cultura correnti. Questa situazione viene illustrata nell'esempio seguente in cui le impostazioni cultura correnti vengono cambiate quattro volte e viene chiamato il metodo DateTime.ToString(String). In ogni caso, la stringa risultante riflette le convenzioni di formattazione delle impostazioni cultura correnti. Questo si verifica perché i metodi DateTime.ToString(), DateTime.ToString(String), DateTimeOffset.ToString()e DateTimeOffset.ToString(String) eseguono il wrapping di chiamate ai metodi DateTime.ToString(String, IFormatProvider) e DateTimeOffset.ToString(String, IFormatProvider) .

using System.Globalization;

public class Example4
{
   public static void Main()
   {
      string[] cultureNames = { "en-US", "fr-FR", "es-MX", "de-DE" };
      DateTime dateToFormat = new DateTime(2012, 5, 28, 11, 30, 0);

      foreach (var cultureName in cultureNames) {
         // Change the current culture.
         CultureInfo.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureName);
         Console.WriteLine($"The current culture is {CultureInfo.CurrentCulture.Name}");
         Console.WriteLine(dateToFormat.ToString("F"));
         Console.WriteLine();
      }
   }
}
// The example displays the following output:
//       The current culture is en-US
//       Monday, May 28, 2012 11:30:00 AM
//
//       The current culture is fr-FR
//       lundi 28 mai 2012 11:30:00
//
//       The current culture is es-MX
//       lunes, 28 de mayo de 2012 11:30:00 a.m.
//
//       The current culture is de-DE
//       Montag, 28. Mai 2012 11:30:00
Imports System.Globalization
Imports System.Threading

Module Example4
    Public Sub Main4()
        Dim cultureNames() As String = {"en-US", "fr-FR", "es-MX", "de-DE"}
        Dim dateToFormat As Date = #5/28/2012 11:30AM#

        For Each cultureName In cultureNames
            ' Change the current culture.
            CultureInfo.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureName)
            Console.WriteLine($"The current culture is {CultureInfo.CurrentCulture.Name}")
            Console.WriteLine(dateToFormat.ToString("F"))
            Console.WriteLine()
        Next
    End Sub
End Module
' The example displays the following output:
'       The current culture is en-US
'       Monday, May 28, 2012 11:30:00 AM
'       
'       The current culture is fr-FR
'       lundi 28 mai 2012 11:30:00
'       
'       The current culture is es-MX
'       lunes, 28 de mayo de 2012 11:30:00 a.m.
'       
'       The current culture is de-DE
'       Montag, 28. Mai 2012 11:30:00 

È anche possibile formattare un valore data e ora per impostazioni cultura specifiche chiamando un overload DateTime.ToString o DateTimeOffset.ToString contenente un parametro provider e passandolo agli elementi seguenti:

  • Oggetto CultureInfo che rappresenta le impostazioni cultura, di cui verranno usate le convenzioni di formattazione. Il metodo CultureInfo.GetFormat restituisce il valore della proprietà CultureInfo.DateTimeFormat , che rappresenta l'oggetto DateTimeFormatInfo che fornisce informazioni di formattazione specifiche delle impostazioni cultura per valori data e ora.

  • Oggetto DateTimeFormatInfo che definisce le convenzioni di formattazione specifiche delle impostazioni cultura da usare. Il metodo GetFormat relativo restituisce un'istanza di se stesso.

Nell'esempio seguente vengono usati gli oggetti DateTimeFormatInfo che rappresentano le impostazioni cultura della lingua Inglese (Stati Uniti) e Inglese (Regno Unito), nonché le impostazioni cultura non associate alle lingue francese e russa per formattare una data.

using System.Globalization;

public class Example5
{
   public static void Main()
   {
      DateTime dat1 = new(2012, 5, 28, 11, 30, 0);
      string[] cultureNames = { "en-US", "en-GB", "ru", "fr" };

      foreach (var name in cultureNames) {
         DateTimeFormatInfo dtfi = CultureInfo.CreateSpecificCulture(name).DateTimeFormat;
         Console.WriteLine($"{name}: {dat1.ToString(dtfi)}");
      }
   }
}
// The example displays the following output:
//       en-US: 5/28/2012 11:30:00 AM
//       en-GB: 28/05/2012 11:30:00
//       ru: 28.05.2012 11:30:00
//       fr: 28/05/2012 11:30:00
Imports System.Globalization

Module Example5
    Public Sub Main5()
        Dim dat1 As Date = #5/28/2012 11:30AM#
        Dim cultureNames() As String = {"en-US", "en-GB", "ru", "fr"}

        For Each name In cultureNames
            Dim dtfi As DateTimeFormatInfo = CultureInfo.CreateSpecificCulture(name).DateTimeFormat
            Console.WriteLine($"{name}: {dat1.ToString(dtfi)}")
        Next
    End Sub
End Module
' The example displays the following output:
'       en-US: 5/28/2012 11:30:00 AM
'       en-GB: 28/05/2012 11:30:00
'       ru: 28.05.2012 11:30:00
'       fr: 28/05/2012 11:30:00

Interfaccia IFormattable

In genere, i tipi che eseguono l'overload del metodo ToString con una stringa di formato e un parametro IFormatProvider implementano anche l'interfaccia IFormattable . Questa interfaccia dispone di un singolo membro, IFormattable.ToString(String, IFormatProvider), che include sia una stringa di formato che un provider di formato come parametri.

L'implementazione dell'interfaccia IFormattable per la classe definita dall'applicazione offre due vantaggi:

Nell'esempio seguente viene definita una classe Temperature che implementa l'interfaccia IFormattable . Sono supportati gli identificatori di formato "C" e "G" per visualizzare la temperatura in Celsius, l'identificatore di formato "F" per visualizzare la temperatura in Fahrenheit e l'identificatore di formato "K" per visualizzare la temperatura in Kelvin.

using System;
using System.Globalization;

namespace HotAndCold
{

    public class Temperature : IFormattable
    {
        private decimal m_Temp;

        public Temperature(decimal temperature)
        {
            this.m_Temp = temperature;
        }

        public decimal Celsius
        {
            get { return this.m_Temp; }
        }

        public decimal Kelvin
        {
            get { return this.m_Temp + 273.15m; }
        }

        public decimal Fahrenheit
        {
            get { return Math.Round((decimal)this.m_Temp * 9 / 5 + 32, 2); }
        }

        public override string ToString()
        {
            return this.ToString("G", null);
        }

        public string ToString(string format)
        {
            return this.ToString(format, null);
        }

        public string ToString(string format, IFormatProvider provider)
        {
            // Handle null or empty arguments.
            if (String.IsNullOrEmpty(format))
                format = "G";
            // Remove any white space and covert to uppercase.
            format = format.Trim().ToUpperInvariant();

            if (provider == null)
                provider = NumberFormatInfo.CurrentInfo;

            switch (format)
            {
                // Convert temperature to Fahrenheit and return string.
                case "F":
                    return this.Fahrenheit.ToString("N2", provider) + "°F";
                // Convert temperature to Kelvin and return string.
                case "K":
                    return this.Kelvin.ToString("N2", provider) + "K";
                // Return temperature in Celsius.
                case "C":
                case "G":
                    return this.Celsius.ToString("N2", provider) + "°C";
                default:
                    throw new FormatException(String.Format("The '{0}' format string is not supported.", format));
            }
        }
    }
Public Class Temperature : Implements IFormattable
    Private m_Temp As Decimal

    Public Sub New(temperature As Decimal)
        Me.m_Temp = temperature
    End Sub

    Public ReadOnly Property Celsius() As Decimal
        Get
            Return Me.m_Temp
        End Get
    End Property

    Public ReadOnly Property Kelvin() As Decimal
        Get
            Return Me.m_Temp + 273.15D
        End Get
    End Property

    Public ReadOnly Property Fahrenheit() As Decimal
        Get
            Return Math.Round(CDec(Me.m_Temp * 9 / 5 + 32), 2)
        End Get
    End Property

    Public Overrides Function ToString() As String
        Return Me.ToString("G", Nothing)
    End Function

    Public Overloads Function ToString(format As String) As String
        Return Me.ToString(format, Nothing)
    End Function

    Public Overloads Function ToString(format As String, provider As IFormatProvider) As String _
       Implements IFormattable.ToString

        ' Handle null or empty arguments.
        If String.IsNullOrEmpty(format) Then format = "G"
        ' Remove any white space and convert to uppercase.
        format = format.Trim().ToUpperInvariant()

        If provider Is Nothing Then provider = NumberFormatInfo.CurrentInfo

        Select Case format
     ' Convert temperature to Fahrenheit and return string.
            Case "F"
                Return Me.Fahrenheit.ToString("N2", provider) & "°F"
     ' Convert temperature to Kelvin and return string.
            Case "K"
                Return Me.Kelvin.ToString("N2", provider) & "K"
     ' Return temperature in Celsius.
            Case "C", "G"
                Return Me.Celsius.ToString("N2", provider) & "°C"
            Case Else
                Throw New FormatException(String.Format($"The '{format}' format string is not supported."))
        End Select
    End Function
End Class

Nell'esempio seguente viene creata un'istanza di un oggetto Temperature . Viene quindi chiamato il metodo ToString e vengono usate diverse stringhe di formato composite per ottenere diverse rappresentazioni di stringa di un oggetto Temperature . Ognuna di queste chiamate al metodo chiama, a sua volta, l'implementazione di IFormattable della classe Temperature .

public class Example11
{
    public static void Main()
    {
        CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo("en-US");
        Temperature temp = new Temperature(22m);
        Console.WriteLine(Convert.ToString(temp, new CultureInfo("ja-JP")));
        Console.WriteLine("Temperature: {0:K}", temp);
        Console.WriteLine("Temperature: {0:F}", temp);
        Console.WriteLine(String.Format(new CultureInfo("fr-FR"), "Temperature: {0:F}", temp));
    }
}
// The example displays the following output:
//       22.00°C
//       Temperature: 295.15K
//       Temperature: 71.60°F
//       Temperature: 71,60°F
Public Module Example12
    Public Sub Main12()
        Dim temp As New Temperature(22D)
        CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo("en-US")
        Console.WriteLine(Convert.ToString(temp, New CultureInfo("ja-JP")))
        Console.WriteLine($"Temperature: {temp:K}")
        Console.WriteLine($"Temperature: {temp:F}")
        Console.WriteLine(String.Format(New CultureInfo("fr-FR"), $"Temperature: {temp:F}"))
    End Sub
End Module
' The example displays the following output:
'       22.00°C
'       Temperature: 295.15K
'       Temperature: 71.60°F
'       Temperature: 71,60°F

Formattazione composita

Alcuni metodi, ad esempio String.Format e StringBuilder.AppendFormat, supportano la formattazione composita. Una stringa di formato composita è un tipo di modello che restituisce una singola stringa che incorpora la rappresentazione di stringa di zero, uno o più oggetti. Ogni oggetto è rappresentato nella stringa di formato composita da un elemento di formato indicizzato. L'indice dell'elemento di formato corrisponde alla posizione dell'oggetto che esso rappresenta nell'elenco di parametri del metodo. Gli indici sono a base zero. Nella chiamata seguente al metodo String.Format , ad esempio, il primo elemento di formato, {0:D}, viene sostituito dalla rappresentazione di stringa thatDate, il secondo elemento di formato, {1}, viene sostituito dalla rappresentazione di stringa item1e il terzo elemento di formato, {2:C2}, viene sostituito dalla rappresentazione di stringa item1.Value.

result = String.Format("On {0:d}, the inventory of {1} was worth {2:C2}.",
                       thatDate, item1, item1.Value);
Console.WriteLine(result);
// The example displays output like the following if run on a system
// whose current culture is en-US:
//       On 5/1/2009, the inventory of WidgetA was worth $107.44.
result = String.Format("On {0:d}, the inventory of {1} was worth {2:C2}.",
                       thatDate, item1, item1.Value)
Console.WriteLine(result)
' The example displays output like the following if run on a system
' whose current culture is en-US:
'       On 5/1/2009, the inventory of WidgetA was worth $107.44.

Oltre a sostituire un elemento di formato con la rappresentazione di stringa dell'oggetto corrispondente, gli elementi di formato consentono anche di controllare gli aspetti seguenti:

  • Il modo specifico in cui un oggetto è rappresentato come stringa, se l'oggetto implementa l'interfaccia IFormattable e supporta le stringhe di formato. A tale scopo, dopo l'indice dell'elemento di formato è necessario aggiungere un simbolo : (due punti) seguito da una stringa di formato valida. Nell'esempio precedente viene eseguita questa operazione formattando un valore di data con la stringa di formato "d" (modello di data breve) (ad esempio, {0:d}) e formattando un valore numerico con la stringa di formato "C2" (ad esempio, {2:C2} ) per rappresentare il numero come valore di valuta con due cifre decimali frazionarie.

  • La larghezza del campo che contiene la rappresentazione di stringa dell'oggetto e l'allineamento della rappresentazione di stringa in tale campo. A tale scopo, dopo l'indice dell'elemento di formato è necessario aggiungere un simbolo , (virgola) seguito dalla larghezza del campo. La stringa viene allineata a destra nel campo se la larghezza del campo è un valore positivo e viene allineata a sinistra se la larghezza del campo è un valore negativo. L'esempio seguente consente di allineare a sinistra i valori di data in un campo di 20 caratteri e di allineare a destra i valori decimali con una cifra frazionaria in un campo di 11 caratteri.

    DateTime startDate = new DateTime(2015, 8, 28, 6, 0, 0);
    decimal[] temps = { 73.452m, 68.98m, 72.6m, 69.24563m,
                       74.1m, 72.156m, 72.228m };
    Console.WriteLine("{0,-20} {1,11}\n", "Date", "Temperature");
    for (int ctr = 0; ctr < temps.Length; ctr++)
       Console.WriteLine("{0,-20:g} {1,11:N1}", startDate.AddDays(ctr), temps[ctr]);
    
    // The example displays the following output:
    //       Date                 Temperature
    //
    //       8/28/2015 6:00 AM           73.5
    //       8/29/2015 6:00 AM           69.0
    //       8/30/2015 6:00 AM           72.6
    //       8/31/2015 6:00 AM           69.2
    //       9/1/2015 6:00 AM            74.1
    //       9/2/2015 6:00 AM            72.2
    //       9/3/2015 6:00 AM            72.2
    
    Dim startDate As New Date(2015, 8, 28, 6, 0, 0)
    Dim temps() As Decimal = {73.452, 68.98, 72.6, 69.24563,
                               74.1, 72.156, 72.228}
    Console.WriteLine("{0,-20} {1,11}", "Date", "Temperature")
    Console.WriteLine()
    For ctr As Integer = 0 To temps.Length - 1
        Console.WriteLine("{0,-20:g} {1,11:N1}", startDate.AddDays(ctr), temps(ctr))
    Next
    ' The example displays the following output:
    '       Date                 Temperature
    '
    '       8/28/2015 6:00 AM           73.5
    '       8/29/2015 6:00 AM           69.0
    '       8/30/2015 6:00 AM           72.6
    '       8/31/2015 6:00 AM           69.2
    '       9/1/2015 6:00 AM            74.1
    '       9/2/2015 6:00 AM            72.2
    '       9/3/2015 6:00 AM            72.2
    

    Si noti che, se il componente stringa di allineamento e il componente stringa di formato sono entrambi presenti, il primo precede il secondo, ad esempio {0,-20:g}.

Per altre informazioni sulla formattazione composita, vedere Composite Formatting.

Formattazione personalizzata con ICustomFormatter

Due metodi di formattazione compositi, String.Format(IFormatProvider, String, Object[]) e StringBuilder.AppendFormat(IFormatProvider, String, Object[]), includono un parametro del provider di formato che supporta la formattazione personalizzata. Quando viene chiamato uno di questi metodi di formattazione, viene passato un oggetto Type che rappresenta un'interfaccia ICustomFormatter al metodo GetFormat del provider di formato. Il metodo GetFormat è quindi responsabile della restituzione dell'implementazione di ICustomFormatter che fornisce formattazione personalizzata.

L'interfaccia ICustomFormatter dispone di un singolo metodo, Format(String, Object, IFormatProvider), chiamato automaticamente da un metodo di formattazione composita una volta per ogni elemento di formato in una stringa di formato composita. Il metodo Format(String, Object, IFormatProvider) dispone di tre parametri: una stringa di formato, che rappresenta l'argomento formatString in un elemento di formato, un oggetto da formattare e un oggetto IFormatProvider che fornisce i servizi di formattazione. In genere, la classe che implementa ICustomFormatter implementa anche IFormatProvider, pertanto quest'ultimo parametro è un riferimento alla classe di formattazione personalizzata stessa. Questo metodo restituisce una rappresentazione di stringa formattata personalizzata dell'oggetto da formattare. Se il metodo non è in grado di formattare l'oggetto, deve restituire un riferimento Null (Nothing in Visual Basic).

Nell'esempio seguente viene fornita un'implementazione di ICustomFormatter denominata ByteByByteFormatter che consente di visualizzare i valori interi come sequenza di valori esadecimali a due cifre seguiti da uno spazio.

public class ByteByByteFormatter : IFormatProvider, ICustomFormatter
{
   public object GetFormat(Type formatType)
   {
      if (formatType == typeof(ICustomFormatter))
         return this;
      else
         return null;
   }

   public string Format(string format, object arg,
                          IFormatProvider formatProvider)
   {
      if (! formatProvider.Equals(this)) return null;

      // Handle only hexadecimal format string.
      if (! format.StartsWith("X")) return null;

      byte[] bytes;
      string output = null;

      // Handle only integral types.
      if (arg is Byte)
         bytes = BitConverter.GetBytes((Byte) arg);
      else if (arg is Int16)
         bytes = BitConverter.GetBytes((Int16) arg);
      else if (arg is Int32)
         bytes = BitConverter.GetBytes((Int32) arg);
      else if (arg is Int64)
         bytes = BitConverter.GetBytes((Int64) arg);
      else if (arg is SByte)
         bytes = BitConverter.GetBytes((SByte) arg);
      else if (arg is UInt16)
         bytes = BitConverter.GetBytes((UInt16) arg);
      else if (arg is UInt32)
         bytes = BitConverter.GetBytes((UInt32) arg);
      else if (arg is UInt64)
         bytes = BitConverter.GetBytes((UInt64) arg);
      else
         return null;

      for (int ctr = bytes.Length - 1; ctr >= 0; ctr--)
         output += String.Format("{0:X2} ", bytes[ctr]);

      return output.Trim();
   }
}
Public Class ByteByByteFormatter : Implements IFormatProvider, ICustomFormatter
    Public Function GetFormat(formatType As Type) As Object _
                    Implements IFormatProvider.GetFormat
        If formatType Is GetType(ICustomFormatter) Then
            Return Me
        Else
            Return Nothing
        End If
    End Function

    Public Function Format(fmt As String, arg As Object,
                           formatProvider As IFormatProvider) As String _
                           Implements ICustomFormatter.Format

        If Not formatProvider.Equals(Me) Then Return Nothing

        ' Handle only hexadecimal format string.
        If Not fmt.StartsWith("X") Then
            Return Nothing
        End If

        ' Handle only integral types.
        If Not typeof arg Is Byte AndAlso
           Not typeof arg Is Int16 AndAlso
           Not typeof arg Is Int32 AndAlso
           Not typeof arg Is Int64 AndAlso
           Not typeof arg Is SByte AndAlso
           Not typeof arg Is UInt16 AndAlso
           Not typeof arg Is UInt32 AndAlso
           Not typeof arg Is UInt64 Then _
              Return Nothing

        Dim bytes() As Byte = BitConverter.GetBytes(arg)
        Dim output As String = Nothing

        For ctr As Integer = bytes.Length - 1 To 0 Step -1
            output += String.Format("{0:X2} ", bytes(ctr))
        Next

        Return output.Trim()
    End Function
End Class

Nell'esempio seguente viene usata la classe ByteByByteFormatter per formattare valori interi. Si noti che il metodo ICustomFormatter.Format viene chiamato più di una volta nella seconda chiamata al metodo String.Format(IFormatProvider, String, Object[]) e che il provider NumberFormatInfo predefinito viene usato nella terza chiamata al metodo, perché il metodoByteByByteFormatter.Format non riconosce la stringa di formato "N0" e restituisce un riferimento Null (Nothing in Visual Basic).

public class Example10
{
   public static void Main()
   {
      long value = 3210662321;
      byte value1 = 214;
      byte value2 = 19;

      Console.WriteLine(String.Format(new ByteByByteFormatter(), "{0:X}", value));
      Console.WriteLine(String.Format(new ByteByByteFormatter(), "{0:X} And {1:X} = {2:X} ({2:000})",
                                      value1, value2, value1 & value2));
      Console.WriteLine(String.Format(new ByteByByteFormatter(), "{0,10:N0}", value));
   }
}
// The example displays the following output:
//       00 00 00 00 BF 5E D1 B1
//       00 D6 And 00 13 = 00 12 (018)
//       3,210,662,321
Public Module Example10
    Public Sub Main10()
        Dim value As Long = 3210662321
        Dim value1 As Byte = 214
        Dim value2 As Byte = 19

        Console.WriteLine((String.Format(New ByteByByteFormatter(), "{0:X}", value)))
        Console.WriteLine((String.Format(New ByteByByteFormatter(), "{0:X} And {1:X} = {2:X} ({2:000})",
                                        value1, value2, value1 And value2)))
        Console.WriteLine(String.Format(New ByteByByteFormatter(), "{0,10:N0}", value))
    End Sub
End Module
' The example displays the following output:
'       00 00 00 00 BF 5E D1 B1
'       00 D6 And 00 13 = 00 12 (018)
'       3,210,662,321

Vedi anche

Title Definizione
Stringhe di formato numerico standard Vengono descritte le stringhe di formato standard che consentono di creare rappresentazioni di stringa usate comunemente di valori numerici.
Stringhe di formato numerico personalizzato Vengono descritte le stringhe di formato personalizzate che consentono di creare formati specifici dell'applicazione per valori numerici.
Stringhe formato data e ora standard Vengono descritte le stringhe di formato standard che consentono di creare rappresentazioni di stringa usate comunemente di valori DateTime .
Stringhe formato data e ora personalizzate Vengono descritte le stringhe di formato personalizzate che consentono di creare formati specifici dell'applicazione per valori DateTime .
Stringhe di formato TimeSpan standard Vengono descritte le stringhe di formato standard che consentono di creare rappresentazioni di stringa usate comunemente di intervalli di tempo.
Stringhe di formato TimeSpan personalizzate Vengono descritte le stringhe di formato personalizzate che consentono di creare formati specifici dell'applicazione per intervalli di tempo.
Enumeration Format Strings Vengono descritte le stringhe di formato standard che consentono di creare rappresentazioni di stringa di valori di enumerazione.
Formattazione composita Viene descritto come incorporare uno o più valori formattati in una stringa, che successivamente può essere visualizzata nella console oppure scritta in un flusso.
Parsing Strings Viene descritta l'inizializzazione di oggetti sui valori descritti dalle rappresentazioni in forma di stringa di tali oggetti. L'analisi è l'operazione contraria alla formattazione.

Riferimento