Literais de cadeia de caracteres brutos

Tip

Este artigo faz parte da secção Fundamentos para programadores que já conhecem pelo menos uma linguagem de programação e estão a aprender C#. Se és novo na programação, começa primeiro pelos tutoriais para começar . Para a gramática completa, consulte a referência linguística.

Vem de outra língua? Os literais de cadeias brutas em C# cumprem o mesmo papel que as cadeias r"..." de Python e Rust, os blocos de texto de Java ("""...""") e as cadeias de templates back-tick em JavaScript, TypeScript e Go. A sintaxe C# é a mais próxima dos blocos de texto do Java, com regras extra para delimitadores de comprimento variável e interpolação.

Um literal bruto de cadeia é delimitado por três ou mais aspas duplas. Dentro dos delimitadores, cada carácter é interpretado literalmente. As citações e barras inversas não precisam de ser escapadas, e as linhas novas são preservadas como estão escritas. Utilize cadeias literais para qualquer cadeia de caracteres que contenha aspas, barras invertidas ou várias linhas: JSON, XML, SQL, expressões regulares, caminhos de ficheiros e exemplos de código.

Warning

Um literal de cadeia em bruto torna o SQL mais fácil de ler, mas não o torna mais seguro. Nunca concatene ou interpole valores fornecidos pelo utilizador num comando SQL. Essa prática abre a sua aplicação à injeção SQL. Usa comandos parametrizados em vez disso: DbCommand.CreateParameter com DbParameterCollection.Add, ou os helpers de nível superior em Entity Framework Core e Dapper. A mesma precaução aplica-se a outros formatos propensos à injeção, como comandos shell, filtros LDAP e HTML.

Um literal que contém aspas e barras inversas

Um literal normal precisa de caracteres de escape para " e \. Um literal verbatim ainda precisa de "" para incorporar uma citação. Um literal em bruto não precisa de nenhum dos dois:

// Same JSON value, three ways:
string regular  = "{ \"name\": \"Ada\", \"path\": \"C:\\\\src\" }";
string verbatim = @"{ ""name"": ""Ada"", ""path"": ""C:\\src"" }";
string raw      = """{ "name": "Ada", "path": "C:\\src" }""";

Console.WriteLine(regular  == raw);   // True
Console.WriteLine(verbatim == raw);   // True

Cada formulário produz a mesma cadeia, mas a versão bruta lê-se exatamente como o JSON que representa.

Cordas brutas de linha única

Os delimitadores de abertura e fecho têm, cada um, pelo menos três aspas duplas, e o delimitador de fecho tem de usar o mesmo número de aspas que o delimitador de abertura. O conteúdo situa-se entre eles na mesma linha. As aspas e barras invertidas dentro do conteúdo são literais:

// A raw string literal starts and ends with at least three quotes.
// Inside, " and \ are literal — no escaping required.
string message = """She said "hi" and left.""";
string regex   = """\d{3}-\d{4}""";

Console.WriteLine(message);   // She said "hi" and left.
Console.WriteLine(regex);     // \d{3}-\d{4}

Uma cadeia raw de uma única linha não pode ser vazia entre os seus delimitadores. Pode acabar com uma dupla citação, mas não pode começar com uma. O compilador trata umas aspas duplas iniciais como um caráter delimitador de abertura adicional. Se o seu conteúdo tiver de começar com uma citação, use em vez disso uma cadeia literal crua de várias linhas, que coloca o conteúdo numa linha própria onde uma citação inicial é inequívoca.

Cadeias de caracteres raw de múltiplas linhas

Para conteúdo multilinha, o delimitador de abertura termina a linha e o delimitador de fecho inicia o seu próprio. Tal como nas cadeias brutas de linha única, o delimitador é composto por três ou mais aspas duplas, e o delimitador de fecho deve usar o mesmo número de aspas que a inicial. Três citações é o caso comum, mas pode usar quatro, cinco ou mais quando o próprio conteúdo contém uma sequência de """. Tudo o que está entre os dois delimitadores é o valor da cadeia, exatamente como está escrito:

// The opening """ and closing """ each sit on their own line.
// The content between them is the value, exactly as written.
string sql = """
    SELECT id, name
    FROM customers
    WHERE active = 1
    """;

Console.WriteLine(sql);

A nova linha imediatamente após a abertura """ e a nova linha imediatamente antes do fecho """ não fazem parte do valor. São delimitadores de espaços em branco. Da mesma forma, o compilador remove qualquer espaço em branco à esquerda do fecho """ de cada linha de conteúdo, para que possa indentar o literal para corresponder ao bloco de código que o encerra sem que essa indentação apareça na cadeia. A secção seguinte aborda esta regra em detalhe.

Se o conteúdo em si contiver uma sequência de """, use quatro ou mais aspas para os delimitadores. O número de delimitadores só tem de exceder a sequência mais longa de aspas no conteúdo. Veja literais de cadeia bruta (referência da linguagem) para ver as regras completas.

Indentação: o delimitador de encerramento define a margem

A coluna do fecho """ define uma margem esquerda. O compilador remove o espaço em branco até essa coluna de cada linha de conteúdo. Esta regra permite-lhe indentar o literal para corresponder ao código circundante sem poluir o valor:

// The column of the closing """ sets a left margin.
// Whitespace up to that column is stripped from every content line.
string xml = """
        <order id="42">
            <item>book</item>
        </order>
        """;

// First content line begins at column 0 of the value:
Console.WriteLine(xml);
/* Output:
   <order id="42">
       <item>book</item>
   </order>
 */

Se uma linha de conteúdo tiver menos caracteres de espaço em branco à esquerda do que a coluna do delimitador de fecho, o compilador reporta um erro. Mantenha todas as linhas de conteúdo indentadas pelo menos tanto quanto o fecho """.

Cadeias de caracteres interpoladas brutas

Adicione um $ prefixo a uma cadeia bruta para permitir a interpolação. As expressões nos {} buracos são avaliadas e os seus resultados são inseridos no valor:

// A single $ before """ enables interpolation: single { and } mark a hole.
// Inside a single-$ raw string, literal braces aren't allowed — use $$ when
// the content also contains literal { or }.
string name = "Ada";
int    score = 95;

string report = $"""
    Player:  {name}
    Score:   {score}
    Updated: {DateTime.UtcNow:yyyy-MM-dd}
    """;

Console.WriteLine(report);

Se o seu conteúdo interpolado também precisar dos caracteres literais { ou }, consulte Literais de cadeia em bruto (referência da linguagem).

Quando escolher que literal

Use uma string literal bruta sempre que o conteúdo contiver citações, barras adicionais ou várias linhas. O resultado é mais curto e fácil de ler, mais fácil de colar para dentro ou para fora, e isento de erros associados a sequências de escape.

Use uma string literal normal para valores curtos e de linha única, sem aspas ou barras inversas, como nomes, mensagens, marcadores de formato.

Utilize um literal de cadeia verbatim (@"...") apenas quando estiver a trabalhar com código existente que o utilize. Para código novo, as cadeias literais brutas abrangem todos os casos abrangidos pelas cadeias literais textuais, com uma sintaxe mais simples para aspas incorporadas.

Consulte também