Por que o .Contains() comum vai te decepcionar (e como corrigir isso)
\n\nImagine: você está escrevendo uma pesquisa de catálogo de livros em C#. O usuário digita «Tolstói», mas no banco de dados está armazenado «tolstói» com letra minúscula. O string.Contains("Tolstói") comum retornará false. Uma dor familiar? Esta pergunta acumulou milhares de visualizações no Stack Overflow — e não é à toa. Em 2025, quando o .NET oferece ferramentas poderosas para trabalhar com strings, usar a abordagem antiga significa perder usuários e desempenho.
Neste artigo, vamos analisar as 5 melhores formas de tornar o .Contains() insensível a maiúsculas/minúsculas em C#. Você descobrirá qual método escolher para máxima velocidade e qual para um funcionamento correto com diferentes idiomas. Vamos lá!
O problema: por que o .Contains() padrão diferencia maiúsculas de minúsculas?
\n\nEm C#, o método string.Contains() padrão usa comparação Ordinal. Isso significa que os caracteres são comparados byte a byte: 'A' (0x41) não é igual a 'a' (0x61). Para conteúdo em inglês, isso geralmente é normal, mas em aplicações multilíngues (russo, alemão, turco), essa abordagem quebra a lógica da pesquisa.
Por exemplo, em turco, a letra 'i' maiúscula é 'İ', não 'I'. Um simples ToLower() pode dar um resultado incorreto. Portanto, simplesmente chamar text.ToLower().Contains(pattern.ToLower()) é uma má prática. Vamos ver as soluções modernas.
Forma 1: StringComparison.OrdinalIgnoreCase — seu novo padrão
\n\nA partir do .NET 5 (e funciona perfeitamente no .NET 8/9), a forma mais rápida e segura é usar a sobrecarga de Contains com o parâmetro StringComparison:
string text = "Guerra e Paz — Lev Tolstói";\nstring searchTerm = "tolstói";\n\nbool result = text.Contains(searchTerm, StringComparison.OrdinalIgnoreCase);\nConsole.WriteLine(result); // True\n\nPor que esta é a melhor escolha?
\n- \n
- Velocidade: OrdinalIgnoreCase funciona no nível de bytes, mas ignora maiúsculas/minúsculas. É 2 a 3 vezes mais rápido que CurrentCultureIgnoreCase. \n
- Previsibilidade: Não depende da cultura do usuário. "ß" (Eszett alemão) não será igual a "ss", se você não quiser. \n
- Suporte: Disponível em todas as versões modernas do .NET (Core 2.1+). \n
Use este método quando precisar de uma comparação simples sem distinção de maiúsculas/minúsculas e não estiver lidando com peculiaridades linguísticas (ordenação, declinações).
\n\nForma 2: IndexOf() com StringComparison — se precisar de mais controle
\n\nÀs vezes, você não precisa apenas verificar a existência, mas também saber a posição da ocorrência. Ou está trabalhando com versões mais antigas do .NET Framework, onde Contains com StringComparison não existe. Nesse caso, o IndexOf() vem em seu auxílio:
string text = "C# — a melhor linguagem para backend";\nstring searchTerm = "Melhor";\n\nbool result = text.IndexOf(searchTerm, StringComparison.OrdinalIgnoreCase) >= 0;\nConsole.WriteLine(result); // True\n\n// E se precisar obter a posição:\nint index = text.IndexOf(searchTerm, StringComparison.OrdinalIgnoreCase);\nConsole.WriteLine(index); // 4 (posição onde a palavra começa)\n\nQuando usar:
\n- \n
- Em projetos legados (por exemplo, .NET Framework 4.x). \n
- Quando precisar encontrar o índice da ocorrência, e não apenas verificar a existência. \n
- Para cenários mais complexos (por exemplo, pesquisa ignorando caracteres). \n
Importante: IndexOf retorna -1 se a substring não for encontrada. Sempre verifique com >= 0, e não com > 0.
Forma 3: CultureInfo.CurrentCultureIgnoreCase — para pesquisa linguisticamente correta
\n\nSe a sua aplicação deve considerar