C# string e StringBuilder
Esta é a página de consulta dos textos no C#: todos os métodos de string que você vai usar no dia a dia e os do StringBuilder, cada um com exemplo e resultado. Para aprender com calma, veja as aulas Strings, Métodos de String, Interpolação e StringBuilder.
Os resultados vêm dos programas desta página, rodados no dotnet 10.0.112 da máquina da Ana (pasta ~/cs/str, cultura pt-BR) e no editor do guia, que deram a mesma saída (a não ser numa linha do rastro de uma exceção, indicada abaixo).
Atalhos: A string não muda · Métodos de string · Métodos de string. · Comparar e ordenar · char · StringBuilder · string ou StringBuilder? · Quando dá errado · Experimente
Antes de tudo: a string não muda
Nenhum método de string muda o texto original. ToUpper, Trim, Replace e todos os outros devolvem uma string nova. Se você não guardar o resultado, ele se perde:
string nome = "ana"; nome.ToUpper(); Console.WriteLine(nome); nome = nome.ToUpper(); Console.WriteLine(nome);
$ dotnet run imut.cs ana ANA
A linha 2 criou "ANA" e jogou fora; só a linha 4, que guarda o resultado em nome, mudou o que a variável mostra. Essa regra (a string é imutável) é o motivo de existir o StringBuilder, no fim desta página.
Métodos de string
Este programa usa os métodos mais comuns. Cada linha da saída começa com o número da linha da tabela:
// metodos.cs — os métodos de string mais usados
string s = " Ana Maria da Silva ";
string nome = "Ana Maria";
Console.WriteLine($"1 [{s.Trim()}] [{s.TrimStart()}] [{s.TrimEnd()}]");
Console.WriteLine($"2 {nome.Length} {nome[0]} {nome[^1]} {nome[4..9]}");
Console.WriteLine($"3 {nome.ToUpper()} {nome.ToLower()} {"ação".ToUpper()}");
Console.WriteLine($"4 {nome.Contains("Maria")} {nome.Contains("maria")} {nome.Contains("maria", StringComparison.OrdinalIgnoreCase)}");
Console.WriteLine($"5 {nome.StartsWith("Ana")} {nome.EndsWith("ia")} {nome.IndexOf('a')} {nome.LastIndexOf('a')} {nome.IndexOf("Maria")} {nome.IndexOf("José")}");
Console.WriteLine($"6 {nome.Substring(4)} | {nome.Substring(0, 3)} | {nome.Replace("Maria", "Clara")} | {nome.Replace('a', 'o')}");
Console.WriteLine($"7 {nome.Insert(3, " Paula")} | {nome.Remove(3)} | {nome.Remove(0, 4)}");
Console.WriteLine($"8 [{"7".PadLeft(3, '0')}] [{"Ana".PadRight(6)}] [{"Ana".PadLeft(6)}]");
string[] partes = "arroz,feijão,,ovos".Split(',');
Console.WriteLine($"9 {partes.Length} [{string.Join("|", partes)}]");
string[] limpas = "arroz, feijão,, ovos".Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
Console.WriteLine($"10 {limpas.Length} [{string.Join("|", limpas)}]");
Console.WriteLine($"11 {string.Concat("a", "b", "c")} {string.Join(", ", ["x", "y", "z"])} {string.Format("{0} tem {1} anos", "Ana", 29)} {new string('-', 5)}");
Console.WriteLine($"12 {string.IsNullOrEmpty("")} {string.IsNullOrEmpty(" ")} {string.IsNullOrWhiteSpace(" ")} {string.IsNullOrWhiteSpace(null)}");
Console.WriteLine($"13 {"ana" == "Ana"} {"ana".Equals("Ana", StringComparison.OrdinalIgnoreCase)} {string.Compare("abacate", "banana")} {string.Compare("b", "a")} {"a".CompareTo("a")}");
char[] letras = nome.ToCharArray();
Array.Reverse(letras);
Console.WriteLine($"14 {new string(letras)} {string.Join("-", nome.Split(' '))} {nome.Count(c => c == 'a')}");
Console.WriteLine($"15 {"maçã".Length} {"🍎".Length} {"olá"[2]} {(int)'á'} {char.IsLetter('á')} {char.IsDigit('7')} {char.ToUpper('é')}");
Console.WriteLine($"16 {"Olá".PadRight(5, '.')}{"Mundo"} {"abc".IndexOfAny(['x', 'b'])} {"a-b-c".Split('-', 2)[1]}");
$ dotnet run metodos.cs 1 [Ana Maria da Silva] [Ana Maria da Silva ] [ Ana Maria da Silva] 2 9 A a Maria 3 ANA MARIA ana maria AÇÃO 4 True False True 5 True True 2 8 4 -1 6 Maria | Ana | Ana Clara | Ano Morio 7 Ana Paula Maria | Ana | Maria 8 [007] [Ana ] [ Ana] 9 4 [arroz|feijão||ovos] 10 3 [arroz|feijão|ovos] 11 abc x, y, z Ana tem 29 anos ----- 12 True False True True 13 False True -1 1 0 14 airaM anA Ana-Maria 3 15 4 2 á 225 True True É 16 Olá..Mundo 1 b-c
Nas tabelas, nome é "Ana Maria" e s é " Ana Maria da Silva " (com dois espaços nas pontas).
Tamanho, posições e pedaços
| Membro | O que faz | Exemplo | Resultado | Aula |
|---|---|---|---|---|
Length | quantos caracteres (propriedade, sem parênteses) | nome.Length | 9 | Strings |
[i] | o caractere da posição i (do 0); é um char | nome[0] · nome[^1] | A · a | Strings |
[a..b] | o pedaço da posição a até antes de b | nome[4..9] | Maria | Índices e Intervalos |
Substring(início) | do início até o fim | nome.Substring(4) | Maria | Métodos de String |
Substring(início, tamanho) | tamanho caracteres a partir do início | nome.Substring(0, 3) | Ana | Métodos de String |
IndexOf(x) | a primeira posição de x (char ou texto), ou -1 | nome.IndexOf('a') · nome.IndexOf("Maria") · nome.IndexOf("José") | 2 · 4 · -1 | Métodos de String |
LastIndexOf(x) | a última posição | nome.LastIndexOf('a') | 8 | Métodos de String |
IndexOfAny(chars) | a primeira posição de qualquer um dos caracteres | "abc".IndexOfAny(['x', 'b']) | 1 | Métodos de String |
Repare no IndexOf('a'): o A maiúsculo da posição 0 não conta. Maiúsculas e minúsculas são caracteres diferentes.
Procurar
| Método | Pergunta | Exemplo | Resultado |
|---|---|---|---|
Contains(x) | tem x em algum lugar? | nome.Contains("Maria") · nome.Contains("maria") | True · False |
Contains(x, StringComparison.OrdinalIgnoreCase) | o mesmo, ignorando maiúsculas | nome.Contains("maria", StringComparison.OrdinalIgnoreCase) | True |
StartsWith(x) | começa com x? | nome.StartsWith("Ana") | True |
EndsWith(x) | termina com x? | nome.EndsWith("ia") | True |
Aula: Métodos de String. Para procurar padrões (um CPF, um e-mail), veja Expressões Regulares.
Transformar (sempre devolvem uma string nova)
| Método | O que faz | Exemplo | Resultado |
|---|---|---|---|
Trim() | tira espaços (e Tab, Enter) das duas pontas | s.Trim() | [Ana Maria da Silva] |
TrimStart(), TrimEnd() | só do começo, só do fim | s.TrimStart() · s.TrimEnd() | [Ana Maria da Silva ] · [ Ana Maria da Silva] |
ToUpper(), ToLower() | maiúsculas, minúsculas (com acentos, na cultura atual) | nome.ToUpper() · "ação".ToUpper() | ANA MARIA · AÇÃO |
Replace(velho, novo) | troca todas as ocorrências | nome.Replace("Maria", "Clara") · nome.Replace('a', 'o') | Ana Clara · Ano Morio |
Insert(posição, texto) | põe o texto na posição | nome.Insert(3, " Paula") | Ana Paula Maria |
Remove(início), Remove(início, quantos) | tira do início até o fim, ou só quantos | nome.Remove(3) · nome.Remove(0, 4) | Ana · Maria |
PadLeft(n, c), PadRight(n, c) | completa até n caracteres com c (espaço, se omitido) | "7".PadLeft(3, '0') · "Ana".PadRight(6) · "Olá".PadRight(5, '.') | [007] · [Ana ] · Olá.. |
ToCharArray() | vira um array de char | Array.Reverse(letras) e new string(letras) | airaM anA |
Aulas: Métodos de String e, para alinhar números, Formatar Números.
Cortar e juntar
| Método | O que faz | Exemplo | Resultado |
|---|---|---|---|
Split(c) | corta em cada c e devolve um string[]; pedaços vazios ficam | "arroz,feijão,,ovos".Split(',') | 4 pedaços: arroz|feijão||ovos |
Split(c, opções) | RemoveEmptyEntries tira os vazios; TrimEntries tira os espaços de cada pedaço .NET 5 | "arroz, feijão,, ovos".Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) | 3 pedaços: arroz|feijão|ovos |
Split(c, n) | no máximo n pedaços; o último fica com o resto | "a-b-c".Split('-', 2)[1] | b-c |
string.Join(sep, itens) | junta, com sep entre os itens | string.Join("-", nome.Split(' ')) | Ana-Maria |
Métodos de string. (chamados pelo tipo)
| Método | O que faz | Exemplo | Resultado | Aula |
|---|---|---|---|---|
string.IsNullOrEmpty(s) | null ou ""? | string.IsNullOrEmpty("") · (" ") | True · False | null |
string.IsNullOrWhiteSpace(s) | null, vazio ou só espaços? (o melhor para validar o que foi digitado) | string.IsNullOrWhiteSpace(" ") · (null) | True · True | |
string.Join(sep, itens) | junta | string.Join(", ", ["x", "y", "z"]) | x, y, z | Métodos de String |
string.Concat(…) | junta sem separador | string.Concat("a", "b", "c") | abc | Strings |
string.Format(modelo, …) | preenche {0}, {1}… (a forma antiga da interpolação) | string.Format("{0} tem {1} anos", "Ana", 29) | Ana tem 29 anos | Interpolação |
new string(c, n) | o caractere c repetido n vezes | new string('-', 5) | ----- | Strings |
string.Empty | o mesmo que "" | string vazio = string.Empty; | "" | Strings |
Comparar e ordenar
// comparar.cs — comparar e ordenar textos
string[] nomes = ["bruno", "Ana", "álvaro", "Carla", "ana"];
Console.WriteLine(string.Join(" ", nomes.Order()));
Console.WriteLine(string.Join(" ", nomes.Order(StringComparer.Ordinal)));
Console.WriteLine($"{string.Compare("a", "B")} {string.Compare("a", "B", StringComparison.Ordinal)}");
Console.WriteLine($"{"Ana".Equals("ana")} {string.Equals("Ana", "ana", StringComparison.OrdinalIgnoreCase)}");
$ dotnet run comparar.cs álvaro ana Ana bruno Carla Ana Carla ana bruno álvaro -1 31 False True
| Forma | Compara como | Exemplo | Resultado |
|---|---|---|---|
a == b, a.Equals(b) | caractere por caractere, maiúsculas contam | "ana" == "Ana" | False |
string.Equals(a, b, StringComparison.OrdinalIgnoreCase) | ignorando maiúsculas | "ana".Equals("Ana", StringComparison.OrdinalIgnoreCase) | True |
string.Compare(a, b), a.CompareTo(b) | ordem de dicionário na cultura atual: negativo se a vem antes, 0 se igual, positivo se depois | string.Compare("abacate", "banana") · ("b", "a") · "a".CompareTo("a") | -1 · 1 · 0 |
StringComparison.Ordinal | pelo código de cada caractere: todas as maiúsculas antes das minúsculas, e os acentos depois de tudo | string.Compare("a", "B", StringComparison.Ordinal) | 31 (positivo: a vem depois de B) |
Na ordem do dicionário (a primeira linha da saída), álvaro fica junto dos a, e ana vem antes de Ana. Na ordem Ordinal (a segunda), as maiúsculas vêm primeiro e o á vai para o fim. Use a cultura para mostrar listas para pessoas e Ordinal para comparar códigos, nomes de arquivo e chaves. Aula: Cultura.
O tipo char
| Expressão | Resultado | Observação |
|---|---|---|
"maçã".Length | 4 | cada letra acentuada é um char |
"🍎".Length | 2 | um emoji ocupa dois char (UTF-16) |
"olá"[2] | á | um char |
(int)'á' | 225 | o código Unicode do caractere |
char.IsLetter('á'), char.IsDigit('7') | True, True | também IsWhiteSpace, IsUpper, IsLower, IsPunctuation |
char.ToUpper('é') | É | também char.ToLower |
nome.Count(c => c == 'a') | 3 | uma string é uma sequência de char: aceita LINQ |
Aula: char e bool.
StringBuilder
O StringBuilder (de System.Text) é um texto que muda: cada Append acrescenta no mesmo objeto, sem criar uma string nova. É o certo para montar um texto em muitos pedaços, num laço.
// sb.cs — StringBuilder
using System.Text;
StringBuilder sb = new();
sb.Append("Lista de compras");
sb.AppendLine(":");
foreach (string item in new[] { "arroz", "feijão", "café" })
{
sb.Append("- ").AppendLine(item);
}
sb.AppendLine($"Total: {3} itens");
Console.Write(sb.ToString());
Console.WriteLine($"Length: {sb.Length}");
sb.Clear();
sb.Append("Ana");
sb.Insert(0, "Sra. ");
sb.Append('!', 3);
sb.Replace("Ana", "Ana Maria");
Console.WriteLine(sb);
sb.Remove(0, 5);
Console.WriteLine(sb);
sb[0] = 'a';
Console.WriteLine($"{sb} {sb.Length} {sb[0]}");
$ dotnet run sb.cs Lista de compras: - arroz - feijão - café Total: 3 itens Length: 57 Sra. Ana Maria!!! Ana Maria!!! ana Maria!!! 12 a
| Membro | O que faz | Exemplo | Aula |
|---|---|---|---|
new StringBuilder() | cria vazio (também new StringBuilder("começo")) | StringBuilder sb = new(); | StringBuilder |
Append(x) | acrescenta no fim (texto, número, char…); devolve o próprio sb, então dá para encadear | sb.Append("- ").AppendLine(item); | |
Append(c, n) | acrescenta o caractere c n vezes | sb.Append('!', 3); | |
AppendLine(x) | acrescenta e quebra a linha (AppendLine() só quebra) | sb.AppendLine(":"); | |
Insert(posição, x) | põe na posição | sb.Insert(0, "Sra. "); | |
Replace(velho, novo) | troca todas as ocorrências, no próprio sb | sb.Replace("Ana", "Ana Maria"); | |
Remove(início, quantos) | tira caracteres | sb.Remove(0, 5); | |
Clear() | esvazia | sb.Clear(); | |
Length | quantos caracteres tem agora (dá para mudar: sb.Length = 0 também esvazia) | sb.Length → 57 | |
[i] | lê e muda um caractere (na string não dá) | sb[0] = 'a'; | |
ToString() | a string pronta | string texto = sb.ToString(); | |
Console.WriteLine(sb) | chama o ToString() sozinho | Console.WriteLine(sb); |
string ou StringBuilder?
| Situação | Use | Por quê |
|---|---|---|
| Juntar poucos pedaços numa linha | interpolação: $"{nome} tem {idade} anos" | mais legível; o compilador já otimiza |
| Juntar os itens de uma lista com separador | string.Join(", ", itens) | uma chamada só, sem laço |
| Montar um texto num laço, pedaço por pedaço (um relatório, um arquivo) | StringBuilder | com += num laço, cada volta copia o texto inteiro para uma string nova; com milhares de voltas, fica muito mais lento |
| Comparar, procurar, cortar | string | o StringBuilder não tem Contains, Split, IndexOf: faça ToString() antes |
Quando dá errado
| Código | Mensagem real (lab) | O que significa e como consertar | Aula |
|---|---|---|---|
nome[0] = 'A'; | error CS0200: A propriedade ou o indexador "string.this[int]" não pode ser atribuído, pois é somente leitura | A string não muda. Crie outra: nome = char.ToUpper(nome[0]) + nome[1..];, ou use um StringBuilder. | Strings |
char inicial = 'An'; | error CS1012: Número excessivo de caracteres no literal de caractere | Aspas simples são para um caractere. Texto vai em aspas duplas: string inicial = "An"; | char e bool |
int idade = "29"; | error CS0029: Não é possível converter implicitamente tipo "string" em "int" | "29" é texto. Converta: int.Parse("29") ou, com o que o usuário digita, int.TryParse. | Parse e TryParse |
"Ana".Substring(1, 5) | System.ArgumentOutOfRangeException: Index and length must refer to a location within the string. (Parameter 'length') | "Início e tamanho têm de caber na string": a partir da posição 1 só há 2 caracteres. Confira o Length antes, ou use [1..]. | Métodos de String |
"Ana"[3] | System.IndexOutOfRangeException: Index was outside the bounds of the array. | As posições de "Ana" vão de 0 a 2. A mensagem fala em "array" mesmo sendo uma string. No lab, o rastro mostra também a linha at System.String.get_Chars(Int32 index); o editor do guia não mostra essa linha. | Strings |
string? apelido = null;apelido.Length | warning CS8602: Desreferência de uma referência possivelmente nula. e, ao rodar, System.NullReferenceException: Object reference not set to an instance of an object. | O compilador avisou, e o programa caiu. Use apelido?.Length ou confira is null antes. | Referências Anuláveis |
nome.ToUpper(); sozinho | (compila, sem aviso, e não muda nada) | Guarde o resultado: nome = nome.ToUpper();. Veja a missão abaixo. | Métodos de String |
Experimente
Missão: o programa deveria limpar os espaços e pôr o nome em maiúsculas, mas mostra [ ana ]. Conserte as linhas 2 e 3 para a saída ser [ANA].
string nome = " ana ";
nome.Trim();
nome.ToUpper();
Console.WriteLine($"[{nome}]");
string nome = " ana ";
nome = nome.Trim();
nome = nome.ToUpper();
Console.WriteLine($"[{nome}]");
Experimente: troque o texto e os métodos e veja o resultado. Tente Replace, Split com outro separador, PadLeft…
string frase = " A Ana ama arroz com feijão ";
Console.WriteLine($"[{frase.Trim()}]");
Console.WriteLine(frase.Trim().ToUpper());
Console.WriteLine(frase.Contains("arroz"));
Console.WriteLine(frase.Trim().Split(' ').Length);
Console.WriteLine(frase.Replace("arroz", "macarrão").Trim());
Console.WriteLine(frase.Count(c => c == 'a'));
Resumo
- A string é imutável: todo método devolve uma string nova. Guarde o resultado.
Lengthe[i](do 0); pedaços comSubstringou[a..b]; posições comIndexOf(-1= não achou).Trim,ToUpper,ToLower,Replace,PadLeft,Insert,Removetransformam;Contains,StartsWith,EndsWithperguntam.Splitcorta (comRemoveEmptyEntrieseTrimEntries);string.Joinjunta.- Para validar entrada,
string.IsNullOrWhiteSpace. Para comparar sem ligar para maiúsculas,StringComparison.OrdinalIgnoreCase. - Muitos pedaços num laço:
StringBuildercomAppend/AppendLinee, no fim,ToString().