Condividi tramite


Formattazione composita

La funzionalità di formattazione composita .NET accetta un elenco di oggetti e una stringa di formato composito come input. Una stringa di formato composito è costituita da testo fisso mescolato con segnaposto indicizzato, denominato elementi di formato. Questi elementi di formato corrispondono agli oggetti nell'elenco. L'operazione di formattazione produce una stringa risultato costituita dal testo fisso originale alternato alla rappresentazione di stringa degli oggetti dell'elenco.

Importante

Invece di usare stringhe di formato composito, è possibile usare stringhe interpolate se il linguaggio e la versione in uso li supportano. Una stringa interpolata contiene espressioni interpolate. Ogni espressione interpolata viene risolta con il valore dell'espressione e inclusa nella stringa di risultato quando viene assegnata la stringa. Per altre informazioni, vedere Interpolazione di stringhe (Riferimenti per C#) e stringhe interpolate (Riferimenti per Visual Basic).

I metodi seguenti supportano la funzionalità di formattazione composita:

Stringa di formato composito

Una stringa di formato composito e un elenco di oggetti vengono usati come argomenti di metodi che supportano la funzionalità di formattazione composita. Una stringa di formato composito è costituita da zero o più esecuzioni di testo fisso mescolato con uno o più elementi di formato. Il testo fisso è qualsiasi stringa scelta e ogni elemento di formato corrisponde a un oggetto o a una struttura boxed nell'elenco. La rappresentazione di stringa di ogni oggetto sostituisce l'elemento di formato corrispondente.

Si consideri il frammento di codice seguente Format :

string.Format("Name = {0}, hours = {1:hh}", "Fred", DateTime.Now);
String.Format("Name = {0}, hours = {1:hh}", "Fred", DateTime.Now)

Il testo fisso è Name = e , hours = . Gli elementi di formato sono {0}, il cui indice pari a 0 corrisponde all'oggetto namee {1:hh}, il cui indice pari a 1 corrisponde all'oggetto DateTime.Now.

Formattare la sintassi degli elementi

Ogni elemento di formato usa il formato seguente ed è costituito dai componenti riportati di seguito:

{index[,width][:formatString]}

Le parentesi graffe corrispondenti ({ e }) sono obbligatorie.

Componente di indicizzazione

Il componente obbligatorio index , detto anche identificatore di parametro, è un numero a partire da 0 che identifica un elemento corrispondente nell'elenco di oggetti. Ovvero, l'elemento di formato il cui specificatore di parametro è 0 formatta il primo oggetto nell'elenco. L'elemento di formato il cui identificatore di parametro è 1 formatta il secondo oggetto nell'elenco, e così via. L'esempio seguente include quattro identificatori di parametro, numerati da zero a tre, per rappresentare numeri primi minori di 10:

string primes = string.Format("Four prime numbers: {0}, {1}, {2}, {3}",
                              2, 3, 5, 7);
Console.WriteLine(primes);

// The example displays the following output:
//      Four prime numbers: 2, 3, 5, 7
Dim primes As String = String.Format("Four prime numbers: {0}, {1}, {2}, {3}",
                                      2, 3, 5, 7)
Console.WriteLine(primes)

'The example displays the following output
'     Four prime numbers 2, 3, 5, 7

Più elementi di formato possono fare riferimento allo stesso elemento nell'elenco di oggetti specificando lo stesso identificatore di parametro. Ad esempio, è possibile formattare lo stesso valore numerico in formato esadecimale, scientifico e numerico specificando una stringa di formato composito, "0x{0:X} {0:E} {0:N}"ad esempio , come illustrato nell'esempio seguente:

string multiple = string.Format("0x{0:X} {0:E} {0:N}",
                                Int64.MaxValue);
Console.WriteLine(multiple);

// The example displays the following output:
//      0x7FFFFFFFFFFFFFFF 9.223372E+018 9,223,372,036,854,775,807.00
Dim multiple As String = String.Format("0x{0:X} {0:E} {0:N}",
                                       Int64.MaxValue)
Console.WriteLine(multiple)

'The example displays the following output
'     0x7FFFFFFFFFFFFFFF 9.223372E+018 9,223,372,036,854,775,807.00

Ogni elemento di formato può fare riferimento a qualsiasi oggetto nell'elenco. Ad esempio, se sono presenti tre oggetti, è possibile formattare il secondo, il primo e il terzo oggetto specificando una stringa di formato composito, {1} {0} {2}ad esempio . Un oggetto a cui non fa riferimento un elemento di formato viene ignorato. Un'eccezione FormatException viene lanciata in fase di esecuzione se uno specificatore di parametro designa un elemento al di fuori dei limiti dell'elenco di oggetti.

Componente di larghezza

Il componente facoltativo width è un intero con segno che indica la larghezza del campo formattato preferita. Se il valore di width è minore della lunghezza della stringa formattata, width viene ignorato e la lunghezza della stringa formattata viene utilizzata come larghezza del campo. I dati formattati nel campo sono allineati a destra se width sono positivi e allineati a sinistra se width sono negativi. Se è necessario il riempimento, viene utilizzato lo spazio bianco. La virgola è obbligatoria se width è specificata.

Nell'esempio seguente vengono definite due matrici, una contenente i nomi dei dipendenti e l'altra contenente le ore che hanno lavorato per due settimane. La stringa di formato composito allinea a sinistra i nomi in un campo di 20 caratteri e allinea a destra le ore in un campo a 5 caratteri. La stringa di formato standard "N1" formatta le ore con una cifra frazionaria.

string[] names = { "Adam", "Bridgette", "Carla", "Daniel",
                   "Ebenezer", "Francine", "George" };
decimal[] hours = { 40, 6.667m, 40.39m, 82,
                    40.333m, 80, 16.75m };

Console.WriteLine("{0,-20} {1,5}\n", "Name", "Hours");

for (int counter = 0; counter < names.Length; counter++)
    Console.WriteLine("{0,-20} {1,5:N1}", names[counter], hours[counter]);

// The example displays the following output:
//      Name                 Hours
//      
//      Adam                  40.0
//      Bridgette              6.7
//      Carla                 40.4
//      Daniel                82.0
//      Ebenezer              40.3
//      Francine              80.0
//      George                16.8
Dim names As String() = {"Adam", "Bridgette", "Carla", "Daniel",
                         "Ebenezer", "Francine", "George"}

Dim hours As Decimal() = {40, 6.667D, 40.39D, 82,
                          40.333D, 80, 16.75D}

Console.WriteLine("{0,-20} {1,5}\n", "Name", "Hours")

For counter = 0 To names.Length - 1
    Console.WriteLine("{0,-20} {1,5:N1}", names(counter), hours(counter))
Next

'The example displays the following output
'     Name                 Hours
'     
'     Adam                  40.0
'     Bridgette              6.7
'     Carla                 40.4
'     Daniel                82.0
'     Ebenezer              40.3
'     Francine              80.0
'     George                16.8

Componente della stringa di formato

Il componente facoltativo formatString è una stringa di formato appropriata per il tipo di oggetto formattato. Puoi specificare:

  • Stringa di formato numerico standard o personalizzata se l'oggetto corrispondente è un valore numerico.
  • Stringa di formato di data e ora standard o personalizzata se l'oggetto corrispondente è un DateTime oggetto .
  • Stringa di formato di enumerazione se l'oggetto corrispondente è un valore di enumerazione.

Se formatString non viene specificato, viene usato l'identificatore di formato generale ("G") per un tipo numerico, di data e ora o di enumerazione. I due punti sono obbligatori se formatString è specificato.

La tabella seguente elenca tipi o categorie di tipi nella libreria di classi .NET che supportano un set predefinito di stringhe di formato e fornisce collegamenti agli articoli che elencano le stringhe di formato supportate. La formattazione delle stringhe è un meccanismo estendibile che consente di definire nuove stringhe di formato per tutti i tipi esistenti e di definire un set di stringhe di formato supportate da un tipo definito dall'applicazione.

Per altre informazioni, vedere gli articoli sull'interfaccia IFormattable e ICustomFormatter .

Tipo o categoria del tipo Visualizza
Tipi di data e ora (DateTime, DateTimeOffset) Formati standard delle stringhe di data e ora

Stringhe formato data e ora personalizzate
Tipi di enumerazione (tutti i tipi derivati da System.Enum) Formato di Enumerazione delle Stringhe
Tipi numerici (BigInteger, Byte, Decimal, Double, Int16, Int32, Int64, SByte, Single, UInt16, UInt32, UInt64) Stringhe di formato numerico standard

Stringhe di formato numerico personalizzato
Guid Guid.ToString(String)
TimeSpan stringhe di formato TimeSpan standard

stringhe di formato TimeSpan personalizzate

Escape di parentesi graffe

Le parentesi graffe di apertura e chiusura vengono interpretate come iniziali e finali di un elemento di formato. Per visualizzare una parentesi graffa di apertura letterale o parentesi graffa di chiusura, è necessario usare una sequenza di escape. Specificare due parentesi graffe di apertura ({{) nel testo fisso per visualizzare una parentesi graffa di apertura ({) o due parentesi graffe di chiusura (}}) per visualizzare una parentesi graffa di chiusura (}).

Le parentesi graffe escape con un elemento di formato vengono analizzate in modo diverso tra .NET e .NET Framework.

.RETE

Le parentesi graffe possono essere precedute da un carattere di escape per un elemento di formato. Si consideri, ad esempio, l'elemento di formato {{{0:D}}}, destinato a visualizzare una parentesi graffa di apertura, un valore numerico formattato come numero decimale e una parentesi graffa di chiusura. L'elemento di formato viene interpretato nel modo seguente:

  1. Le prime due parentesi graffe di apertura ({{) sono con escape e producono una parentesi graffa di apertura.
  2. I tre caratteri successivi ({0:) vengono interpretati come l'inizio di un elemento di formato.
  3. Il carattere successivo (D) viene interpretato come identificatore di formato numerico standard decimale.
  4. La parentesi graffa successiva (}) viene interpretata come fine dell'elemento di formato.
  5. Le due parentesi graffe finali vengono escape e producono una parentesi graffa di chiusura.
  6. Il risultato finale visualizzato è la stringa letterale, {6324}.
int value = 6324;
string output = string.Format("{{{0:D}}}", value);

Console.WriteLine(output);
// The example displays the following output:
//       {6324}
Dim value As Integer = 6324
Dim output As String = String.Format("{{{0:D}}}", value)

Console.WriteLine(output)

'The example displays the following output
'      {6324}

.NET Framework

Le parentesi graffe in un elemento di formato vengono interpretate in sequenza nell'ordine in cui appaiono. L'interpretazione delle parentesi graffe annidate non è supportata.

Il modo in cui le parentesi graffe con escape vengono interpretate può causare risultati imprevisti. Si consideri, ad esempio, l'elemento di formato {{{0:D}}}, destinato a visualizzare una parentesi graffa di apertura, un valore numerico formattato come numero decimale e una parentesi graffa di chiusura. Tuttavia, l'elemento di formato viene interpretato nel modo seguente:

  1. Le prime due parentesi graffe di apertura ({{) sono con escape e producono una parentesi graffa di apertura.
  2. I tre caratteri successivi ({0:) vengono interpretati come l'inizio di un elemento di formato.
  3. Il carattere successivo (D) verrà interpretato come specificatore di formato numerico standard Decimal, ma le due parentesi graffe successive precedute da uno slash inverso (}}) generano una singola parentesi graffa. Poiché la stringa risultante (D}) non è un identificatore di formato numerico standard, la stringa risultante viene interpretata come stringa di formato personalizzata che significa visualizzare la stringa D}letterale .
  4. L'ultima parentesi graffa (}) viene interpretata come la fine dell'elemento di formato.
  5. Il risultato finale visualizzato è la stringa letterale, {D}. Il valore numerico da formattare non viene visualizzato.
int value = 6324;
string output = string.Format("{{{0:D}}}",
                              value);
Console.WriteLine(output);

// The example displays the following output:
//       {D}
Dim value As Integer = 6324
Dim output As String = String.Format("{{{0:D}}}",
                                     value)
Console.WriteLine(output)

'The example displays the following output:
'      {D}

Un modo per scrivere il codice per evitare l'errata interpretazione delle parentesi graffe scappate e degli elementi di formato consiste nel formattare separatamente le parentesi graffe e gli elementi di formato. Ovvero, nella prima operazione di formattazione, visualizzare letteralmente una parentesi graffa di apertura. Nell'operazione successiva visualizzare il risultato dell'elemento di formato e nell'operazione finale visualizzare una parentesi graffa di chiusura letterale. L'esempio seguente illustra questo approccio:

int value = 6324;
string output = string.Format("{0}{1:D}{2}",
                             "{", value, "}");
Console.WriteLine(output);

// The example displays the following output:
//       {6324}
Dim value As Integer = 6324
Dim output As String = String.Format("{0}{1:D}{2}",
                                     "{", value, "}")
Console.WriteLine(output)

'The example displays the following output:
'      {6324}

Ordine di elaborazione

Se la chiamata al metodo di formattazione composita include un argomento IFormatProvider il cui valore non è null, il runtime chiama il metodo IFormatProvider.GetFormat per richiedere un'implementazioneICustomFormatter. Se il metodo può restituire un'implementazione ICustomFormatter , viene memorizzato nella cache durante la chiamata del metodo di formattazione composita.

Ogni valore nell'elenco di parametri che corrisponde a un elemento di formato viene convertito in una stringa come indicato di seguito:

  1. Se il valore da formattare è null, viene restituita una stringa String.Empty vuota.

  2. Se è disponibile un'implementazione ICustomFormatter , il runtime chiama il relativo Format metodo. Il runtime passa al metodo il valore dell'elemento di formato formatString (o null se non è presente). Il runtime passa anche l'implementazione IFormatProvider al metodo . Se la chiamata al ICustomFormatter.Format metodo restituisce null, l'esecuzione procede con il passaggio successivo. In caso contrario, viene restituito il risultato della ICustomFormatter.Format chiamata.

  3. Se il valore implementa l'interfaccia IFormattable , viene chiamato il metodo dell'interfaccia ToString(String, IFormatProvider) . Se uno è presente nell'elemento di formato, il valore formatString viene passato al metodo. In caso contrario, null viene passato. L'argomento IFormatProvider viene determinato nel modo seguente:

  4. Viene chiamato il metodo senza parametri del tipo, che esegue l'override di ToString oppure eredita il comportamento della classe base. In questo caso, la stringa di formato specificata dal formatString componente nell'elemento di formato, se presente, viene ignorata.

L'allineamento viene applicato dopo l'esecuzione dei passaggi precedenti.

Esempi di codice

L'esempio seguente mostra una stringa creata usando la formattazione composita e un'altra creata usando il metodo di ToString un oggetto. Entrambi i tipi di formattazione producono risultati equivalenti.

string formatString1 = string.Format("{0:dddd MMMM}", DateTime.Now);
string formatString2 = DateTime.Now.ToString("dddd MMMM");
Dim formatString1 As String = String.Format("{0:dddd MMMM}", DateTime.Now)
Dim formatString2 As String = DateTime.Now.ToString("dddd MMMM")

Supponendo che il giorno corrente sia un giovedì di maggio, il valore di entrambe le stringhe nell'esempio precedente è Thursday May nella cultura inglese degli Stati Uniti.

Console.WriteLine espone la stessa funzionalità di String.Format. L'unica differenza tra i due metodi è che String.Format restituisce il risultato come stringa, mentre Console.WriteLine scrive il risultato nel flusso di output associato all'oggetto Console . Nell'esempio seguente viene utilizzato il Console.WriteLine metodo per formattare il valore di myNumber in un valore di valuta:

int myNumber = 100;
Console.WriteLine($"{myNumber:C}");

// The example displays the following output
// if en-US is the current culture:
//        $100.00
Dim myNumber As Integer = 100
Console.WriteLine("{0:C}", myNumber)

'The example displays the following output
'if en-US Is the current culture:
'       $100.00

L'esempio seguente illustra la formattazione di più oggetti, inclusa la formattazione di un oggetto in due modi diversi:

string myName = "Fred";
Console.WriteLine(string.Format("Name = {0}, hours = {1:hh}, minutes = {1:mm}",
                                myName, DateTime.Now));

// Depending on the current time, the example displays output like the following:
//        Name = Fred, hours = 11, minutes = 30
Dim myName As String = "Fred"
Console.WriteLine(String.Format("Name = {0}, hours = {1:hh}, minutes = {1:mm}",
                                myName, DateTime.Now))
'Depending on the current time, the example displays output Like the following:
'       Name = Fred, hours = 11, minutes = 30

Nell'esempio seguente viene illustrato l'uso della larghezza nella formattazione. Gli argomenti formattati vengono posizionati tra i caratteri della barra verticale (|) per evidenziare l'allineamento risultante.

string firstName = "Fred";
string lastName = "Opals";
int myNumber = 100;

string formatFirstName = string.Format("First Name = |{0,10}|", firstName);
string formatLastName = string.Format("Last Name =  |{0,10}|", lastName);
string formatPrice = string.Format("Price =      |{0,10:C}|", myNumber);
Console.WriteLine(formatFirstName);
Console.WriteLine(formatLastName);
Console.WriteLine(formatPrice);
Console.WriteLine();

formatFirstName = string.Format("First Name = |{0,-10}|", firstName);
formatLastName = string.Format("Last Name =  |{0,-10}|", lastName);
formatPrice = string.Format("Price =      |{0,-10:C}|", myNumber);
Console.WriteLine(formatFirstName);
Console.WriteLine(formatLastName);
Console.WriteLine(formatPrice);

// The example displays the following output on a system whose current
// culture is en-US:
//     First Name = |      Fred|
//     Last Name =  |     Opals|
//     Price =      |   $100.00|
//
//     First Name = |Fred      |
//     Last Name =  |Opals     |
//     Price =      |$100.00   |
Dim firstName As String = "Fred"
Dim lastName As String = "Opals"
Dim myNumber As Integer = 100

Dim formatFirstName As String = String.Format("First Name = |{0,10}|", firstName)
Dim formatLastName As String = String.Format("Last Name =  |{0,10}|", lastName)
Dim formatPrice As String = String.Format("Price =      |{0,10:C}|", myNumber)
Console.WriteLine(formatFirstName)
Console.WriteLine(formatLastName)
Console.WriteLine(formatPrice)
Console.WriteLine()

formatFirstName = String.Format("First Name = |{0,-10}|", firstName)
formatLastName = String.Format("Last Name =  |{0,-10}|", lastName)
formatPrice = String.Format("Price =      |{0,-10:C}|", myNumber)
Console.WriteLine(formatFirstName)
Console.WriteLine(formatLastName)
Console.WriteLine(formatPrice)

'The example displays the following output on a system whose current
'culture Is en-US:
'    First Name = |      Fred|
'    Last Name =  |     Opals|
'    Price =      |   $100.00|
'
'    First Name = |Fred      |
'    Last Name =  |Opals     |
'    Price =      |$100.00   |

Vedere anche