L'interpolazione di stringhe costruisce una stringa a partire da testo letterale ed espressioni. Metti $ davanti al letterale, scrivi una qualsiasi espressione C# tra graffe, e il suo valore viene convertito in testo e inserito:
Output:
Hello, Maya!
3 items at 4.5 = 13.5
Name has 4 letters, upper: MAYA
Free shipping: yes
L'interpolazione è arrivata in C# 6. Il compilatore la trasforma in una chiamata a string.Format o string.Concat (oppure, da C# 10, in codice handler più efficiente), quindi non è più lenta che costruire la stringa a mano.
L'espressione condizionale nell'ultima riga ha bisogno delle parentesi. Dentro uno spazio di interpolazione, i due punti iniziano uno specificatore di formato, quindi {x > 10 ? "yes" : "no"} senza parentesi è un errore di compilazione.
Specificatori di formato
Dopo l'espressione, i due punti e una stringa di formato controllano come viene scritto il valore. Le stesse stringhe di formato funzionano con ToString("...") e string.Format.
Output:
1234567.89
1,234,567.89
1,234,568
00042
FF
00ff
1.23E+006
0.813
81.3%
1,234,567.89
007.5
3.1
I codici standard, ognuno seguito facoltativamente da un numero di precisione:
| Codice | Nome | Esempio | Risultato |
|---|---|---|---|
F o F2 | Virgola fissa | {3.14159:F2} | 3.14 |
N o N0 | Numero con separatori delle migliaia | {1234.56:N0} | 1,235 |
C | Valuta (simbolo e formato della cultura) | {9.5:C} in en-US | $9.50 |
D5 | Intero con zeri iniziali | {42:D5} | 00042 |
X, x | Esadecimale | {255:X} | FF |
E2 | Scientifico | {1234.5:E2} | 1.23E+003 |
P1 | Percentuale (moltiplica per 100) | {0.256:P1} in en-US | 25.6% |
G | Generale (il più breve) | {2.50m:G} | 2.50 |
R | Round-trip (double) | {0.1:R} | 0.1 |
I formati personalizzati costruiscono un formato a partire da segnaposto: 0 è una cifra sempre mostrata, # è una cifra mostrata solo se significativa, . è il separatore decimale, , dentro il numero attiva i separatori delle migliaia, e % moltiplica per 100. "0.##" mostra fino a due decimali ed elimina gli zeri finali; "#,##0.00" è il classico formato contabile.
Tutta la formattazione numerica arrotonda il valore mostrato; la variabile in sé resta invariata. Quando un valore sta esattamente a metà (2.25 mostrato con un decimale), runtime e tipi diversi possono arrotondare il pareggio in modo diverso, quindi se la regola conta arrotonda prima in modo esplicito con Math.Round(value, 1, MidpointRounding.AwayFromZero) e poi formatta.
Date nell'interpolazione
I valori DateTime accettano allo stesso modo le stringhe di formato per le date:
Output:
2026-09-24
24/09/2026 16:05
Thu, Sep 24
Shipped at 16:05 on Thursday
ETA 02:10
2.2 hours
Un formato personalizzato di TimeSpan richiede che i caratteri letterali siano preceduti da un backslash, che in un letterale stringa normale si scrive \\:. L'elenco completo dei codici per le date (yyyy, MM, HH, tt...) e gli errori tipici (mm sono i minuti, MM i mesi) si trovano in formato DateTime.
Allineamento e riempimento
Una virgola dopo l'espressione imposta una larghezza minima del campo. Un numero positivo allinea a destra, un numero negativo allinea a sinistra. Insieme a un formato, permette di incolonnare tabelle in testo semplice:
Output:
Item | Price| Sold
----------------------------
Espresso | 2.40| 118
Latte | 3.60| 64
Hot chocolate | 4.25| 9
La sintassi è {expression,alignment:format}: prima l'allineamento, poi il formato. Un valore più lungo della larghezza non viene troncato; sposta in avanti il resto della riga. PadLeft e PadRight fanno lo stesso riempimento fuori dall'interpolazione.
Escape delle graffe
Per stampare una graffa letterale, raddoppiala: {{ e }}. Capita quando l'output è JSON, CSS o codice:
Output:
{ "id": 42, "name": "Ana" }
Set literal: {1, 2, 3}
{42}
Costruire JSON a mano in questo modo va bene per una rapida riga di log; per il JSON vero usa un serializzatore, che gestisce correttamente le virgolette e i caratteri speciali dentro name.
string.Format e formattazione composita
Prima di C# 6 la formattazione si faceva con string.Format, che accetta segnaposto numerati e una lista di argomenti. La stessa sintassi di formattazione composita è accettata da Console.WriteLine, StringBuilder.AppendFormat e TextWriter.Write:
Output:
Notebook x4: 14.00
Notebook | 3.50
echo echo !
Dear Leo, your order #000731 has shipped.
Nel codice preferisci l'interpolazione: i valori stanno dove compaiono, quindi un segnaposto non può puntare all'argomento sbagliato. string.Format resta lo strumento giusto quando il modello è un dato, come un messaggio tradotto caricato da un file di risorse. Un indice di segnaposto senza un argomento corrispondente ({2} con due argomenti) lancia una FormatException in esecuzione.
Cultura: controllare separatori e valuta
Interpolazione, ToString e string.Format usano tutti di default la cultura corrente del thread. Su una macchina impostata in tedesco (o in italiano), {1234.5:N2} produce 1.234,50; negli Stati Uniti produce 1,234.50. Il formato valuta C usa il simbolo della cultura. Per scegliere la cultura in modo esplicito, cattura la stringa interpolata come FormattableString e formattala con un provider:
Output:
Total: 1,234.50
Total: 1.234,50
$1,234.50
1.234,50
1234.5,0.75
Usa la cultura dell'utente per il testo che leggono le persone, e CultureInfo.InvariantCulture per tutto ciò che legge un altro programma. Un CSV scritto con la cultura corrente su una macchina tedesca ha virgole dentro i numeri ed è illeggibile altrove. Su .NET 6 e successivi, string.Create(CultureInfo.InvariantCulture, $"...") fa lo stesso di FormattableString.Invariant senza l'oggetto intermedio.
Stringhe interpolate verbatim e raw
$ si combina con @ per una stringa interpolata verbatim: i backslash sono letterali e la stringa può estendersi su più righe. C# 8 e successivi accettano entrambi gli ordini ($@ o @$); C# 6 e 7 richiedono $@:
Output:
C:\Users\ana\Reports\2026\summary.txt
Report for ana
Year: 2026
C# 11 ha aggiunto le stringhe interpolate raw. Con un solo $, le graffe indicano le espressioni come al solito. Con $$, una graffa singola è letterale e le espressioni richiedono due graffe, il che rende leggibili i modelli JSON e di codice:
// C# 11 and later
int id = 42;
string name = "Ana";
string json = $$"""
{
"id": {{id}},
"name": "{{name}}"
}
""";
C# 11 permette anche di andare a capo dentro uno spazio di interpolazione, così un'espressione lunga o un'espressione switch si può dividere su più righe.
Errori comuni
- Dimenticare il
$."Total: {total}"stampa le graffe letteralmente. Il compilatore non avvisa. - Un operatore ternario senza parentesi dentro le graffe: i due punti vengono letti come separatore del formato.
- Formattare l'output per le macchine con la cultura corrente. Le virgole decimali rompono CSV, JSON e SQL. Usa la cultura invariante.
- Usare
ToString()senza formato per gli importi.2.5mviene stampato come2.5, non2.50. UsaF2,N2oC. - Costruire stringhe grandi con l'interpolazione in un ciclo. Ogni iterazione crea una nuova stringa; usa StringBuilder o
string.Join.
Domande frequenti
Cos'è l'interpolazione di stringhe in C#?
Un letterale stringa preceduto da $ in cui le espressioni tra graffe vengono valutate e inserite: $"Total: {price * qty}". È stata aggiunta in C# 6 e sostituisce la maggior parte degli usi di string.Format e della concatenazione con +. Tra le graffe funziona qualsiasi espressione, comprese chiamate di metodo e accesso a proprietà.
Come formatto un numero con 2 cifre decimali in C#?
Aggiungi uno specificatore di formato dopo i due punti: $"{price:F2}" stampa 2 cifre dopo il separatore decimale, e $"{price:N2}" fa lo stesso con i separatori delle migliaia. Fuori dall'interpolazione, gli stessi codici funzionano con price.ToString("F2"). Entrambi arrotondano il valore per la visualizzazione senza modificarlo.
Come faccio l'escape delle graffe in una stringa interpolata C#?
Raddoppiale: {{ stampa { e }} stampa }. Per esempio $"{{ \"id\": {id} }}" stampa { "id": 42 }. Nelle stringhe interpolate raw di C# 11 puoi invece iniziare il letterale con $$, così le graffe singole sono letterali e {{expr}} indica un'espressione.
Che differenza c'è tra string.Format e l'interpolazione di stringhe?
Producono lo stesso risultato con gli stessi codici di formato. string.Format("{0} costs {1:F2}", name, price) fa riferimento agli argomenti per posizione; $"{name} costs {price:F2}" mette le espressioni direttamente nel testo, quindi si legge più facilmente e non può sbagliare l'ordine degli argomenti. string.Format serve ancora quando la stringa di formato stessa arriva da un file di risorse o da un database.
Perché il mio numero interpolato mostra una virgola invece di un punto?
L'interpolazione formatta con la cultura corrente del thread, e molte culture, compresa quella italiana, usano la virgola come separatore decimale. Per l'output letto da programmi (file, JSON, URL), formatta con la cultura invariante: FormattableString.Invariant($"{value:F2}"), oppure su .NET 6 e successivi string.Create(CultureInfo.InvariantCulture, $"...").