C# Métodos de String

Na aula Strings você aprendeu a criar, medir e comparar textos. Agora vem a caixa de ferramentas: tirar espaços que o usuário digitou sem querer, procurar uma palavra, recortar o dia de uma data, trocar uma palavra por outra, separar uma lista em itens. Cada uma dessas tarefas é um método da string, uma ação que você pede escrevendo texto.Metodo(...). Nesta aula você vai conhecer os mais usados, o que cada um devolve e como eles quebram quando recebem uma posição que não existe.

Você vai aprender
  • Limpar: Trim, TrimStart, TrimEnd e as maiúsculas com ToUpper/ToLower.
  • Procurar: Contains, StartsWith, EndsWith, IndexOf e o famoso -1.
  • Recortar: Substring e os intervalos data[..2].
  • Trocar e dividir: Replace, Split, string.Join, PadLeft/PadRight, Insert/Remove.
  • Encadear métodos (texto.Trim().ToLower()) e os erros reais quando a posição não existe.

Todos os programas desta aula foram rodados com o .NET 10 na máquina fictícia da Ana (usuária ana, computador notebook), na pasta ~/cs, com dotnet run arquivo.cs.


A ideia: pedir para a string fazer algo

Pense na string como um funcionário que sabe fazer várias tarefas com o próprio texto. Você chama pelo nome e pede: "nome, me dá você em maiúsculas" (nome.ToUpper()), "frase, você contém a palavra roupa?" (frase.Contains("roupa")).

Duas regras valem para todos os métodos desta aula:

  1. O ponto liga o texto ao método, e os parênteses vêm sempre, mesmo vazios: nome.Trim(). O que vai dentro dos parênteses são os argumentos, os detalhes do pedido: frase.Replace("café", "chá").
  2. A string original nunca muda. Strings são imutáveis (aula Strings): o método devolve um resultado novo. Se você quer usar esse resultado depois, guarde numa variável: email = email.Trim();.

1. Maiúsculas e minúsculas

string nome = "Ana Souza";
Console.WriteLine(nome.ToUpper());
Console.WriteLine(nome.ToLower());
Console.WriteLine(nome);
$ dotnet run caixa.cs
ANA SOUZA
ana souza
Ana Souza     « a original não mudou

ToUpper ("para cima") e ToLower ("para baixo") seguem as regras do idioma do computador e conhecem os acentos ("ação" vira "AÇÃO"). Os detalhes, inclusive o "i" turco e o ToUpperInvariant, estão em Strings.


2. Limpar espaços: Trim

Quando alguém digita um e-mail, é comum sobrar um espaço no começo ou no fim. Para o computador, " ana@email.com" e "ana@email.com" são textos diferentes. O Trim ("aparar") tira os espaços das pontas:

string digitado = "   ana@email.com  ";
Console.WriteLine("[" + digitado + "]");
Console.WriteLine("[" + digitado.Trim() + "]");
Console.WriteLine("[" + digitado.TrimStart() + "]");
Console.WriteLine("[" + digitado.TrimEnd() + "]");
Console.WriteLine("[" + "...oi!!!".Trim('.', '!') + "]");
$ dotnet run trim.cs
[   ana@email.com  ]
[ana@email.com]        « Trim: as duas pontas
[ana@email.com  ]      « TrimStart: só o começo
[   ana@email.com]     « TrimEnd: só o fim
[oi]                   « Trim com caracteres escolhidos
"[" + … + "]"
Os colchetes são só um truque para ver os espaços na tela. Sem eles, espaços no fim da linha são invisíveis.
Trim()
Tira espaços, tabulações e quebras de linha do começo e do fim. Os espaços do meio ficam: " Ana Souza ".Trim() dá "Ana Souza".
Trim('.', '!')
Com argumentos, tira das pontas os caracteres que você escolheu (em aspas simples, porque são char).

3. Procurar: Contains, StartsWith, EndsWith, IndexOf

string frase = "O rato roeu a roupa do rei de Roma";
Console.WriteLine(frase.Contains("roupa"));
Console.WriteLine(frase.Contains("Roupa"));
Console.WriteLine(frase.Contains("ROMA", StringComparison.OrdinalIgnoreCase));
Console.WriteLine(frase.StartsWith("O rato"));
Console.WriteLine(frase.EndsWith("Roma"));
Console.WriteLine(frase.IndexOf("ro"));
Console.WriteLine(frase.LastIndexOf("ro"));
Console.WriteLine(frase.IndexOf('R'));
Console.WriteLine(frase.IndexOf("gato"));
$ dotnet run procurar.cs
True     « "roupa" aparece na frase
False    « maiúsculas contam: "Roupa" não aparece
True     « ignorando maiúsculas, "ROMA" aparece
True     « começa com "O rato"
True     « termina com "Roma"
7        « o primeiro "ro" (de "roeu") começa na posição 7
14       « o último "ro" (de "roupa") começa na posição 14
30       « o 'R' de "Roma"
-1       « "gato" não está na frase
Contains("roupa")
"Contém?" Responde true ou false. Diferencia maiúsculas, a não ser que você passe StringComparison.OrdinalIgnoreCase como segundo argumento.
StartsWith / EndsWith
"Começa com?" e "termina com?". Muito usados com nomes de arquivo: arquivo.EndsWith(".txt").
IndexOf("ro")
"Em que posição está?" Devolve a posição do primeiro caractere da primeira ocorrência, contando do zero. LastIndexOf procura a última. Aceita uma string ("ro") ou um char ('R').
-1
Quando o texto não é encontrado, IndexOf devolve -1, uma posição que não existe. Sempre confira o -1 antes de usar a posição; senão, o próximo método quebra (veja Quando dá errado).

4. Recortar: Substring e intervalos

Para pegar um pedaço do texto, diga onde ele começa e quantos caracteres tem:

string data = "17/10/2026";
string dia = data.Substring(0, 2);
string mes = data.Substring(3, 2);
string ano = data.Substring(6);
Console.WriteLine(dia + " | " + mes + " | " + ano);
Console.WriteLine(data[..2]);
Console.WriteLine(data[3..5]);
Console.WriteLine(data[6..]);
Console.WriteLine(data[^4..]);
$ dotnet run recortar.cs
17 | 10 | 2026
17
10
2026
2026
Posição0123456789
Caractere17/10/2026
A string "17/10/2026": o mês começa na posição 3 e tem 2 caracteres.
Substring(0, 2)
"Pedaço a partir da posição 0, com 2 caracteres". O segundo número é o tamanho, não a posição final: Substring(3, 2) pega as posições 3 e 4.
Substring(6)
Com um número só: da posição 6 até o fim.
data[..2] C# 8
O intervalo (range) diz "do começo até a posição 2, sem incluir a 2". data[3..5] pega 3 e 4; data[6..], da 6 até o fim; data[^4..], os 4 últimos. Aqui os dois números são posições (início e fim), não posição e tamanho. Os detalhes estão em Índices e Intervalos.

Qual usar? Os dois funcionam. O intervalo é mais curto e ótimo para "os 3 primeiros" ([..3]) e "os 4 últimos" ([^4..]). O Substring aparece em todo código antigo e é o que você vai ver em muitos tutoriais.


5. Trocar, inserir e remover

string frase = "Eu gosto de café. Café é bom.";
Console.WriteLine(frase.Replace("café", "chá"));
Console.WriteLine(frase.Replace("Café", "Chá").Replace("café", "chá"));
Console.WriteLine("1.234,50".Replace(".", "").Replace(",", "."));
Console.WriteLine("a-b-c".Replace("-", ""));
Console.WriteLine("Ana Souza".Remove(3));
Console.WriteLine("Ana Souza".Insert(3, " M."));
$ dotnet run trocar.cs
Eu gosto de chá. Café é bom.     « só o "café" minúsculo foi trocado
Eu gosto de chá. Chá é bom.      « dois Replace seguidos
1234.50                          « tirou o ponto e trocou a vírgula por ponto
abc                              « trocar por "" é apagar
Ana                              « Remove(3): apaga da posição 3 até o fim
Ana M. Souza                     « Insert(3, …): enfia o texto na posição 3
Replace("café", "chá")
"Troque todas as ocorrências do primeiro pelo segundo". Diferencia maiúsculas.
.Replace(…).Replace(…)
Como o Replace devolve uma string, dá para chamar outro método direto nela. Isso se chama encadear; veja a seção 8.
Remove(3) e Insert(3, " M.")
Apagar a partir de uma posição e enfiar um texto numa posição. Menos usados, mas úteis.

6. Dividir e juntar: Split e string.Join

A lista de compras da Ana chegou num texto só, separado por ponto e vírgula. O Split ("dividir") corta o texto em pedaços e devolve um array de strings (uma fileira de textos numerados, aula Arrays). O string.Join ("juntar") faz o contrário:

string compras = "arroz;feijão;café;leite";
string[] itens = compras.Split(';');
Console.WriteLine(itens.Length);
Console.WriteLine(itens[0]);
Console.WriteLine(itens[3]);
Console.WriteLine(string.Join(", ", itens));
Console.WriteLine(string.Join(" | ", itens));
string frase = "  muitos   espaços  aqui ";
string[] palavras = frase.Split(' ', StringSplitOptions.RemoveEmptyEntries);
Console.WriteLine(palavras.Length);
Console.WriteLine(string.Join("-", palavras));
$ dotnet run split.cs
4                              « quatro itens
arroz                          « o primeiro, posição 0
leite                          « o último, posição 3
arroz, feijão, café, leite
arroz | feijão | café | leite
3                              « sem as "palavras vazias" entre espaços seguidos
muitos-espaços-aqui
string[] itens = compras.Split(';');
string[] é "array de strings". O ';' é o separador (um char, entre aspas simples), e ele some do resultado. itens.Length diz quantos pedaços saíram; itens[0] é o primeiro.
string.Join(", ", itens)
Junta todos os itens, com ", " entre eles (não no fim). Repare que é string.Join, chamado no tipo, e não itens.Join.
StringSplitOptions.RemoveEmptyEntries
"Remova as entradas vazias". Sem isso, cada par de espaços seguidos geraria um pedaço vazio ("") no array.

Experimente: acrescente itens à lista, troque o separador do Join por " e " ou "\n" (quebra de linha), e mostre quantos itens há. O que acontece se a lista terminar com ;?

string compras = "arroz;feijão;café";
string[] itens = compras.Split(';');
Console.WriteLine("Itens: " + itens.Length);
Console.WriteLine(string.Join(", ", itens));
Console.WriteLine("Primeiro: " + itens[0].ToUpper());

7. Preencher: PadLeft e PadRight

Para alinhar colunas, os métodos Pad ("enchimento") completam o texto até um tamanho:

Console.WriteLine("Arroz".PadRight(10, '.') + "R$ 5,90");
Console.WriteLine("Feijão".PadRight(10, '.') + "R$ 8,50");
Console.WriteLine("7".PadLeft(3, '0'));
Console.WriteLine("[" + "oi".PadLeft(5) + "]");
Console.WriteLine(new string('=', 20));
$ dotnet run pad.cs
Arroz.....R$ 5,90
Feijão....R$ 8,50
007
[   oi]
====================
PadRight(10, '.')
Completa à direita com pontos até o texto ter 10 caracteres. "Arroz" tem 5, então ganha 5 pontos; "Feijão" tem 6, ganha 4. Os preços ficam alinhados.
PadLeft(3, '0')
Completa à esquerda. Bom para números com zeros na frente: 007.
PadLeft(5)
Sem o segundo argumento, completa com espaços.
new string('=', 20)
Não é um método, mas é útil aqui: cria uma string com o caractere '=' repetido 20 vezes, ótimo para linhas de separação.

Para alinhar números e preços, a formatação com {preco,10:C} é ainda mais prática (aula Formatar Números).


8. Encadear métodos

Como cada método devolve uma string nova, você pode chamar o próximo método direto no resultado, da esquerda para a direita:

string resposta = "  SIM  ";
string limpa = resposta.Trim().ToLower();
Console.WriteLine("[" + limpa + "]");
Console.WriteLine(limpa == "sim");
Console.WriteLine("  Ana Souza ".Trim().ToUpper().Replace(" ", "_"));
$ dotnet run cadeia.cs
[sim]
True
ANA_SOUZA
  1. resposta.Trim() devolve "SIM".
  2. "SIM".ToLower() devolve "sim", que vai para limpa.
  3. Na última linha: "Ana Souza" → "ANA SOUZA" → "ANA_SOUZA".

Encadear é ótimo para duas ou três etapas. Com mais, quebre em variáveis com nomes claros: fica mais fácil achar onde está um erro.

Missão: a pessoa respondeu " SIM ", com espaços e em maiúsculas, e o programa precisa da resposta limpa: [sim]. Encadeie Trim() e ToLower() na linha marcada.

[sim]
Confirmou? True
string resposta = "  SIM  ";
string limpa = resposta;     // limpe aqui
Console.WriteLine("[" + limpa + "]");
Console.WriteLine("Confirmou? " + (limpa == "sim"));
string resposta = "  SIM  ";
string limpa = resposta.Trim().ToLower();
Console.WriteLine("[" + limpa + "]");
Console.WriteLine("Confirmou? " + (limpa == "sim"));

Formas diferentes de fazer a mesma coisa

TarefaFormasQual usar
Os 3 primeiros caracteress.Substring(0, 3) · s[..3]s[..3] no código novo; as duas quebram se o texto tiver menos de 3.
Contém, sem ligar para maiúsculass.ToLower().Contains("ana") · s.Contains("ana", StringComparison.OrdinalIgnoreCase)A segunda: não cria uma string nova e não depende do idioma.
Trocar ; por , s.Replace(";", ", ") · string.Join(", ", s.Split(';'))Replace: mais simples. Use Split quando precisar mexer em cada item.
Saber se existes.IndexOf("x") != -1 · s.Contains("x")Contains. Use IndexOf quando precisar da posição.

Quando dá errado

System.ArgumentOutOfRangeException: Index and length must refer to a location within the string.
string nome = "Ana";
Console.WriteLine(nome.Substring(1, 5));
$ dotnet run em1.cs
Unhandled exception. System.ArgumentOutOfRangeException: Index and length must refer to a location within the string. (Parameter 'length')
   at System.String.ThrowSubstringArgumentOutOfRange(Int32 startIndex, Int32 length)
   at System.String.Substring(Int32 startIndex, Int32 length)
   at Program.<Main>$(String[] args) in /home/ana/cs/em1.cs:line 2

O que significa: "a posição e o tamanho precisam caber dentro da string". A partir da posição 1 de "Ana" só há 2 caracteres, e você pediu 5. O (Parameter 'length') aponta o culpado: o argumento do tamanho. As linhas at System.String… são de dentro do .NET; a sua é a última, line 2.

Como consertar: confira o tamanho antes (nome.Length) ou use Substring(1), "até o fim".

System.ArgumentOutOfRangeException: length ('-1') must be a non-negative value. depois de um IndexOf
string email = "ana.email.com";
int arroba = email.IndexOf('@');
Console.WriteLine(arroba);
Console.WriteLine(email.Substring(arroba + 1));
Console.WriteLine(email.Substring(0, arroba));
$ dotnet run em2.cs
-1                « não tem @ no texto
ana.email.com     « Substring(-1 + 1) = Substring(0): o texto todo, sem erro, mas errado
Unhandled exception. System.ArgumentOutOfRangeException: length ('-1') must be a non-negative value. (Parameter 'length')
Actual value was -1.
   at System.ArgumentOutOfRangeException.ThrowNegative[T](T value, String paramName)
   at System.ArgumentOutOfRangeException.ThrowIfNegative[T](T value, String paramName)
   at System.String.ThrowSubstringArgumentOutOfRange(Int32 startIndex, Int32 length)
   at System.String.Substring(Int32 startIndex, Int32 length)
   at Program.<Main>$(String[] args) in /home/ana/cs/em2.cs:line 5

O que significa: o e-mail não tinha @, o IndexOf devolveu -1, e esse -1 foi usado como tamanho: "o tamanho (-1) precisa ser não negativo". Pior: a linha 4 não quebrou, só deu um resultado errado.

Como consertar: confira o -1 antes de usar a posição: if (arroba == -1) { … } (aula if e else), ou use email.Contains('@') antes.

error CS1503: Argumento 1: não é possível converter de "grupo de métodos" para "bool"
string nome = "Ana";
Console.WriteLine(nome.ToUpper);
$ dotnet run em3.cs
/home/ana/cs/em3.cs(2,19): error CS1503: Argumento 1: não é possível converter de "grupo de métodos" para "bool"

Ocorreu uma falha no build. Corrija os erros de build e execute novamente.

O que significa: faltaram os parênteses. Sem eles, nome.ToUpper é o nome do método (um "grupo de métodos"), e não o resultado de chamá-lo. A mensagem fala em bool porque o compilador tentou encaixar isso na primeira versão do WriteLine que encontrou.

Como consertar: nome.ToUpper(). Métodos sempre levam parênteses; propriedades, como Length, não.

error CS0029: Não é possível converter implicitamente tipo "string[]" em "string"
string compras = "arroz;feijão";
string itens = compras.Split(';');
$ dotnet run em4.cs
/home/ana/cs/em4.cs(2,16): error CS0029: Não é possível converter implicitamente tipo "string[]" em "string"

Ocorreu uma falha no build. Corrija os erros de build e execute novamente.

O que significa: o Split devolve vários textos (um string[]), e você tentou guardar numa variável de um texto.

Como consertar: string[] itens = compras.Split(';'); (ou var itens = …, aula var).

O Trim (ou o Replace) "não funcionou"

O que significa: você escreveu email.Trim(); numa linha sozinha e depois usou email. O resultado foi jogado fora.

Como consertar: email = email.Trim();.


Referência

MétodoDevolveExemplo → resultado
ToUpper(), ToLower()string"Ana".ToUpper() → "ANA"
Trim(), TrimStart(), TrimEnd()string" oi ".Trim() → "oi"
Contains(x)bool"banana".Contains("nan") → true
StartsWith(x), EndsWith(x)bool"foto.png".EndsWith(".png") → true
IndexOf(x), LastIndexOf(x)int (ou -1)"banana".IndexOf('n') → 2
Substring(inicio, tamanho)string"banana".Substring(1, 3) → "ana"
s[inicio..fim]string"banana"[1..4] → "ana"
Replace(velho, novo)string"banana".Replace("a", "o") → "bonono"
Insert(pos, x), Remove(pos)string"oi".Insert(2, "!") → "oi!"
Split(sep)string[]"a;b".Split(';') → ["a", "b"]
string.Join(sep, itens)stringstring.Join("-", itens) → "a-b"
PadLeft(n, c), PadRight(n, c)string"7".PadLeft(3, '0') → "007"
new string(c, n)stringnew string('-', 3) → "---"

Muitos aceitam um StringComparison no fim para ignorar maiúsculas: Contains, StartsWith, EndsWith, IndexOf, Replace. A lista completa, com StringBuilder, está em string e StringBuilder.


Exercícios

1. Tirar os espaços

Complete para tirar os espaços do começo e do fim:

nome = nome.;

2. Não achou

O que "banana".IndexOf("uva") devolve?

Resposta:

3. Recortar

Complete para pegar "10" de "17/10/2026" com Substring:

data.Substring()

4. O que "a,b,,c".Split(',').Length devolve?

5. Depois de string s = " oi "; s.Trim();, quanto vale s.Length?

6. Em Substring(3, 2), o que é o 2?

Missão final: separar o e-mail

Missão: a Ana recebeu o e-mail " Ana.Souza@Email.COM ", com espaços e maiúsculas misturadas. Limpe (Trim e ToLower) e separe a parte antes do @ (o usuário) da parte depois (o domínio), usando IndexOf e Substring (ou Split). Não escreva os resultados à mão.

Usuário: ana.souza
Domínio: email.com
string email = "  Ana.Souza@Email.COM ";
// 1. limpe o e-mail
// 2. ache a posição do @
string usuario = "?";
string dominio = "?";
Console.WriteLine("Usuário: " + usuario);
Console.WriteLine("Domínio: " + dominio);
string email = "  Ana.Souza@Email.COM ";
email = email.Trim().ToLower();
int arroba = email.IndexOf('@');
string usuario = email.Substring(0, arroba);
string dominio = email.Substring(arroba + 1);
Console.WriteLine("Usuário: " + usuario);
Console.WriteLine("Domínio: " + dominio);

Com Split, a solução fica: string[] partes = email.Trim().ToLower().Split('@'); e depois partes[0] e partes[1]. Teste também um e-mail sem @ e veja qual exceção aparece.


Resumo

  • Métodos se chamam com ponto e parênteses: texto.Trim(). Eles devolvem um resultado novo; a string original não muda.
  • Limpar: Trim; maiúsculas: ToUpper/ToLower.
  • Procurar: Contains, StartsWith, EndsWith (dão bool) e IndexOf (dá a posição, ou -1 se não achar).
  • Recortar: Substring(inicio, tamanho) ou s[inicio..fim] (o fim não entra). Fora dos limites: ArgumentOutOfRangeException.
  • Trocar: Replace. Dividir e juntar: Split (devolve string[]) e string.Join.
  • Alinhar: PadLeft/PadRight. Repetir: new string('-', 20).
  • Encadeie poucos métodos (s.Trim().ToLower()) e sempre confira o -1 do IndexOf.