Substring retorna uma nova string feita de parte de uma existente. Ele tem duas sobrecargas:
s.Substring(startIndex): destartIndexaté o fim.s.Substring(startIndex, length):lengthcaracteres, começando emstartIndex.
Os índices começam em 0, e o segundo argumento é um tamanho, não uma posição final. Essa é a diferença para o substring(start, end) do JavaScript e o substring(begin, end) do Java, e a origem de muitos bugs de posição errada quando o código é portado.
Saída:
4271-BLK
SHOE
4271
BLK
0
SHOE-4271-BLK
Como todo método de string, Substring não modifica a original; ele retorna uma string nova, então atribua o resultado.
ArgumentOutOfRangeException e como evitá-la
Substring lança ArgumentOutOfRangeException quando o intervalo pedido não cabe na string: um startIndex negativo, um startIndex maior que Length, um length negativo ou startIndex + length maior que Length. Não há truncamento silencioso, ao contrário das fatias do Python.
Saída:
Substring(2, 4) -> "ffee"
Substring(2, 5) -> ArgumentOutOfRangeException
Substring(6) -> ""
Substring(7) -> ArgumentOutOfRangeException
Substring(-1) -> ArgumentOutOfRangeException
Substring(0, 10) -> ArgumentOutOfRangeException
A proteção usual é limitar o tamanho ao que sobra da string com Math.Min:
Saída:
ffee
ea
[]
[]
Chamar Substring em uma string null lança NullReferenceException, não ArgumentOutOfRangeException, e é por isso que o auxiliar verifica null primeiro.
Os primeiros e os últimos n caracteres
Pegar um prefixo ou um sufixo é o uso mais comum de Substring. Os dois lançam exceção quando a string é mais curta que n, então código de produção verifica o tamanho:
Saída:
**** 1111
An Unexpecte...
Hi
Hi
Quando o que você quer descartar é o começo da string, Substring(n) sozinho basta: "#FF8800".Substring(1) é "FF8800". O método relacionado Remove(start, count) faz o inverso de Substring: retorna a string sem aquele intervalo.
Substring com IndexOf
A maioria das substrings reais é encontrada, não contada. IndexOf retorna a posição de um caractere ou de uma string (ou -1 se não estiver lá), e LastIndexOf busca a partir do fim. Combine-os com Substring para cortar o texto em volta de um separador:
Saída:
maya.lopez
example.com
pdf
report.final.v2
WARN
Disk almost full
A aritmética segue uma regra: para pegar o texto entre as posições a e b (sem incluir nenhuma das duas), o início é a + 1 e o tamanho é b - a - 1.
O perigo é o IndexOf retornar -1. email.Substring(0, -1) lança exceção e, pior, email.Substring(-1 + 1) retorna a string inteira sem aviso. Sempre verifique:
Saída:
shop.io
(none)
Split como alternativa
Quando uma string é uma lista de campos com um separador, Split é mais simples que uma cadeia de chamadas a IndexOf e Substring, e não tem aritmética de índices para errar:
Saída:
Ana Silva
Porto
maya.lopez
beach.jpg
Split aloca um array mais uma string por campo, então para um único corte em um laço crítico IndexOf e Substring são mais baratos. Em todos os outros casos, a legibilidade vence. Mais opções (vários separadores, remover entradas vazias, quantidade máxima) estão em métodos de string. Para padrões como "os dígitos depois de ID:", uma expressão regular costuma ser a ferramenta mais clara.
O operador de intervalo (C# 8 em diante)
O C# 8 adicionou a sintaxe de índices e intervalos, que funciona em strings e arrays. ^n significa "n a partir do fim" e a..b é o intervalo de a até b, sem incluir b, então o segundo número é um índice final, não um tamanho:
// C# 8 and later
string sku = "SHOE-4271-BLK";
string first4 = sku[..4]; // "SHOE" same as Substring(0, 4)
string middle = sku[5..9]; // "4271" same as Substring(5, 4)
string last3 = sku[^3..]; // "BLK" same as Substring(sku.Length - 3)
string noEnds = sku[1..^1]; // "HOE-4271-BL" drop first and last
char lastChar = sku[^1]; // 'K'
Em uma string, um intervalo é compilado como uma chamada a Substring, então aloca uma string nova e lança ArgumentOutOfRangeException nos mesmos casos fora dos limites. Qual usar é questão de estilo; intervalos se leem melhor quando as duas pontas são medidas de lados diferentes ([1..^1]).
Substrings sem cópia: Span
Toda chamada a Substring aloca uma string nova. Em código de parsing sensível a desempenho (ler arquivos grandes, tratar muitas requisições), o .NET Core 2.1 em diante oferece ReadOnlySpan<char>, uma visão de parte da string original sem cópia:
ReadOnlySpan<char> line = "2026-09-24,42.50,EUR".AsSpan();
ReadOnlySpan<char> amount = line.Slice(11, 5); // "42.50", no allocation
decimal value = decimal.Parse(amount, provider: CultureInfo.InvariantCulture);
Spans não podem ser guardados em campos de classes comuns nem usados através de um await, então pertencem a código síncrono e enxuto. Para código de aplicação típico, Substring é a ferramenta certa.
Erros comuns
- Passar um índice final como tamanho.
s.Substring(2, 5)significa cinco caracteres a partir do índice 2, não "do índice 2 ao 5". Para pegar o texto do índiceaaté o índiceb, sem incluirb, o tamanho éb - a. - Não verificar se o
IndexOfdeu -1. Ou uma exceção ou, com+ 1, a string inteira por acidente. - Supor que strings curtas são longas o bastante. Um nome, um código ou uma linha de um arquivo pode ser mais curto do que você espera. Limite com
Math.Minou verifique oLength. - Descartar o resultado.
s.Substring(1);sozinho em uma linha não faz nada útil.
Perguntas frequentes
Como o Substring funciona em C#?
s.Substring(start) retorna os caracteres do índice start até o fim; s.Substring(start, length) retorna length caracteres começando em start. Os índices começam em 0, e o segundo argumento é um tamanho, não um índice final: "Hello".Substring(1, 3) é "ell". A string original não é alterada.
Por que o Substring lança ArgumentOutOfRangeException?
Porque start é negativo ou maior que o tamanho da string, ou start + length passa do fim. A causa mais comum é um tamanho calculado para uma string mais longa, ou um resultado -1 do IndexOf usado como início. Limite o tamanho com Math.Min(length, s.Length - start) e verifique os resultados do IndexOf antes de usá-los.
Como pegar os últimos n caracteres de uma string em C#?
s.Substring(s.Length - n) retorna os últimos n caracteres, desde que n <= s.Length. Para ser seguro com strings curtas, use s.Length <= n ? s : s.Substring(s.Length - n). No C# 8 em diante você também pode escrever s[^n..], que lança exceção do mesmo jeito quando n é grande demais.
Como pegar a substring entre dois caracteres em C#?
Encontre as duas posições com IndexOf e pegue a parte entre elas: int start = s.IndexOf('(') + 1; int end = s.IndexOf(')', start); string inside = s.Substring(start, end - start);. Verifique se cada IndexOf encontrou algo (não -1) antes de chamar Substring. Para padrões complexos, uma expressão regular é mais clara.
O Substring começa do zero em C#?
Sim. O primeiro caractere está no índice 0 e o último em Length - 1. Substring(0, 3) retorna os três primeiros caracteres. Passar o próprio Length como início é permitido e retorna uma string vazia.