A interpolação de strings monta uma string a partir de texto literal e expressões. Prefixe o literal com $, coloque qualquer expressão C# entre chaves, e o valor dela é convertido em texto e inserido:
Saída:
Hello, Maya!
3 items at 4.5 = 13.5
Name has 4 letters, upper: MAYA
Free shipping: yes
A interpolação chegou no C# 6. O compilador a transforma em uma chamada a string.Format ou string.Concat (ou, desde o C# 10, em código de handler mais eficiente), então ela não é mais lenta que montar a string à mão.
A expressão condicional da última linha precisa de parênteses. Dentro de um trecho de interpolação, dois pontos iniciam um especificador de formato, então {x > 10 ? "yes" : "no"} sem parênteses é um erro de compilação.
Especificadores de formato
Depois da expressão, dois pontos e uma string de formato controlam como o valor é escrito. As mesmas strings de formato funcionam com ToString("...") e string.Format.
Saída:
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
Os códigos padrão, cada um opcionalmente seguido de um número de precisão:
| Código | Nome | Exemplo | Resultado |
|---|---|---|---|
F ou F2 | Ponto fixo | {3.14159:F2} | 3.14 |
N ou N0 | Número com separadores de grupo | {1234.56:N0} | 1,235 |
C | Moeda (símbolo e padrão da cultura) | {9.5:C} em en-US | $9.50 |
D5 | Inteiro preenchido com zeros | {42:D5} | 00042 |
X, x | Hexadecimal | {255:X} | FF |
E2 | Científico | {1234.5:E2} | 1.23E+003 |
P1 | Percentual (multiplica por 100) | {0.256:P1} em en-US | 25.6% |
G | Geral (o mais curto) | {2.50m:G} | 2.50 |
R | Ida e volta (double) | {0.1:R} | 0.1 |
Padrões personalizados montam um formato a partir de marcadores: 0 é um dígito sempre mostrado, # é um dígito mostrado só se for significativo, . é o ponto decimal, , dentro do número ativa os separadores de grupo, e % multiplica por 100. "0.##" mostra até duas casas decimais e descarta os zeros à direita; "#,##0.00" é o formato contábil clássico.
Toda formatação numérica arredonda o valor exibido; a variável em si não muda. Quando um valor fica exatamente na metade (2.25 mostrado com uma casa decimal), runtimes e tipos diferentes podem arredondar o empate de formas diferentes, então, se a regra importa, arredonde explicitamente antes com Math.Round(value, 1, MidpointRounding.AwayFromZero) e depois formate.
Datas na interpolação
Valores DateTime recebem strings de formato de data do mesmo jeito:
Saída:
2026-09-24
24/09/2026 16:05
Thu, Sep 24
Shipped at 16:05 on Thursday
ETA 02:10
2.2 hours
Um formato personalizado de TimeSpan exige que os caracteres literais sejam escapados com uma barra invertida, o que em um literal de string comum se escreve \\:. A lista completa dos códigos de data (yyyy, MM, HH, tt...) e os erros que as pessoas cometem com eles (mm é minutos, MM é meses) estão em formato de DateTime.
Alinhamento e preenchimento
Uma vírgula depois da expressão define uma largura mínima de campo. Um número positivo alinha à direita, um negativo alinha à esquerda. Combinado com um formato, ele alinha tabelas em texto puro:
Saída:
Item | Price| Sold
----------------------------
Espresso | 2.40| 118
Latte | 3.60| 64
Hot chocolate | 4.25| 9
A sintaxe é {expression,alignment:format}: primeiro o alinhamento, depois o formato. Um valor maior que a largura não é truncado; ele empurra o resto da linha. PadLeft e PadRight fazem o mesmo preenchimento fora da interpolação.
Escapando chaves
Para imprimir uma chave literal, duplique-a: {{ e }}. Isso aparece quando a saída é JSON, CSS ou código:
Saída:
{ "id": 42, "name": "Ana" }
Set literal: {1, 2, 3}
{42}
Montar JSON à mão assim serve para uma linha de log rápida; para JSON de verdade, use um serializador, que trata corretamente aspas e caracteres especiais dentro de name.
string.Format e formatação composta
Antes do C# 6, a formatação era feita com string.Format, que recebe marcadores numerados e uma lista de argumentos. A mesma sintaxe de formatação composta é aceita por Console.WriteLine, StringBuilder.AppendFormat e TextWriter.Write:
Saída:
Notebook x4: 14.00
Notebook | 3.50
echo echo !
Dear Leo, your order #000731 has shipped.
Prefira a interpolação no código: os valores ficam onde aparecem, então um marcador não tem como apontar para o argumento errado. string.Format continua sendo a ferramenta certa quando o modelo é um dado, como uma mensagem traduzida carregada de um arquivo de recursos. Um índice de marcador sem argumento correspondente ({2} com dois argumentos) lança uma FormatException em tempo de execução.
Cultura: controlando separadores e moeda
A interpolação, o ToString e o string.Format usam por padrão a cultura atual da thread. Em uma máquina configurada em alemão, {1234.5:N2} produz 1.234,50; nos EUA produz 1,234.50. O formato de moeda C usa o símbolo da cultura. Para escolher a cultura explicitamente, capture a string interpolada como FormattableString e formate-a com um provedor:
Saída:
Total: 1,234.50
Total: 1.234,50
$1,234.50
1.234,50
1234.5,0.75
Use a cultura do usuário para textos que pessoas leem, e CultureInfo.InvariantCulture para tudo o que outro programa lê. Um CSV gravado com a cultura atual em uma máquina alemã tem vírgulas dentro dos números e fica ilegível em outros lugares. No .NET 6 em diante, string.Create(CultureInfo.InvariantCulture, $"...") faz o mesmo que FormattableString.Invariant, sem o objeto intermediário.
Strings interpoladas verbatim e raw
$ se combina com @ em uma string interpolada verbatim: as barras invertidas são literais e a string pode ocupar várias linhas. O C# 8 em diante aceita as duas ordens ($@ ou @$); o C# 6 e o 7 exigem $@:
Saída:
C:\Users\ana\Reports\2026\summary.txt
Report for ana
Year: 2026
O C# 11 adicionou as raw interpolated strings. Com um $, as chaves marcam expressões como de costume. Com $$, uma chave simples é literal e as expressões precisam de duas chaves, o que deixa legíveis os modelos de JSON e de código:
// C# 11 and later
int id = 42;
string name = "Ana";
string json = $$"""
{
"id": {{id}},
"name": "{{name}}"
}
""";
O C# 11 também permite quebras de linha dentro de um trecho de interpolação, então uma expressão longa ou uma expressão switch pode ser dividida em várias linhas.
Erros comuns
- Esquecer o
$."Total: {total}"imprime as chaves literalmente. O compilador não avisa. - Um ternário sem parênteses dentro das chaves: os dois pontos são lidos como separador de formato.
- Formatar saídas lidas por máquinas com a cultura atual. Vírgulas decimais quebram CSV, JSON e SQL. Use a cultura invariante.
- Usar
ToString()sem formato para dinheiro.2.5mé impresso como2.5, não2.50. UseF2,N2ouC. - Montar strings grandes com interpolação em um laço. Cada iteração cria uma string nova; use StringBuilder ou
string.Join.
Perguntas frequentes
O que é interpolação de strings em C#?
Um literal de string prefixado com $ em que as expressões entre chaves são avaliadas e inseridas: $"Total: {price * qty}". Ela foi adicionada no C# 6 e substitui a maioria dos usos de string.Format e da concatenação com +. Qualquer expressão funciona entre as chaves, inclusive chamadas de métodos e acesso a propriedades.
Como formatar um número com 2 casas decimais em C#?
Adicione um especificador de formato depois de dois pontos: $"{price:F2}" imprime 2 dígitos depois do ponto decimal, e $"{price:N2}" faz o mesmo com separadores de milhar. Fora da interpolação, os mesmos códigos funcionam com price.ToString("F2"). Os dois arredondam o valor para exibição sem alterá-lo.
Como escapar chaves em uma string interpolada em C#?
Duplique-as: {{ imprime { e }} imprime }. Por exemplo, $"{{ \"id\": {id} }}" imprime { "id": 42 }. Nas raw interpolated strings do C# 11, você pode começar o literal com $$, para que chaves simples sejam literais e {{expr}} marque uma expressão.
Qual a diferença entre string.Format e interpolação de strings?
Elas produzem o mesmo resultado com os mesmos códigos de formato. string.Format("{0} costs {1:F2}", name, price) se refere aos argumentos pela posição; $"{name} costs {price:F2}" coloca as expressões no próprio texto, então é mais fácil de ler e não tem como errar a ordem dos argumentos. string.Format ainda é necessário quando a própria string de formato vem de um arquivo de recursos ou de um banco de dados.
Por que meu número interpolado aparece com vírgula em vez de ponto?
A interpolação formata com a cultura atual da thread, e muitas culturas, como a do Brasil, usam a vírgula como separador decimal. Para saídas lidas por máquinas (arquivos, JSON, URLs), formate com a cultura invariante: FormattableString.Invariant($"{value:F2}"), ou no .NET 6 em diante string.Create(CultureInfo.InvariantCulture, $"...").