Case insensitive 'Contains(string)'
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
A case-insensitive “contains” check sounds simple, but the best implementation depends on the language and on whether you care about culture-specific text rules. In C#, the most direct approach is to use an API that accepts StringComparison instead of lowercasing both strings manually.
Use Contains with StringComparison
Modern .NET provides an overload that makes the intent explicit.
This is usually the best answer because it avoids allocating lowercased copies unnecessarily and makes the comparison mode visible in the code.
Why OrdinalIgnoreCase Is Often the Right Default
StringComparison.OrdinalIgnoreCase performs a case-insensitive comparison based on character values rather than culture rules. That is usually the safest default for technical identifiers, file-like paths, protocol tokens, and general non-linguistic matching.
If you really need culture-aware behavior for user-facing natural language, a culture-specific comparison may be more appropriate, but most application “contains” checks do not need that complexity.
Older Fallback: IndexOf
If you are targeting an older framework or prefer wider compatibility, IndexOf with StringComparison works well too.
This is historically common and still perfectly valid.
Why ToLower() Is Not the Best First Choice
A lot of examples use this pattern:
It works in many cases, but it has drawbacks:
- it creates extra string allocations
- it hides the comparison semantics
- it can introduce culture-sensitive surprises if you use culture-aware casing unintentionally
Using StringComparison is usually clearer and more robust.
Null Handling Matters
If either string can be null, guard that explicitly.
In real code, you may prefer early validation instead of packing all null logic into one line, but the point is that nullability should be handled intentionally.
When Culture-Sensitive Matching Makes Sense
For user-visible linguistic text, culture can matter. In those cases, you may choose CurrentCultureIgnoreCase instead of OrdinalIgnoreCase.
This is a semantics choice, not just a syntax preference. Pick the mode that matches the problem domain.
For many backend and tooling scenarios, choosing OrdinalIgnoreCase also makes behavior easier to test because the result does not depend on the current UI culture of the machine running the code.
The General Principle in Other Languages
Even outside C#, the same principle holds: prefer built-in case-insensitive comparison support when it exists, and normalize strings manually only when the language or API leaves you no better option.
That is why the real lesson is not “always lowercase both strings.” It is “choose an API that expresses comparison rules clearly.”
Common Pitfalls
A common mistake is lowercasing both strings by habit instead of using a comparison overload that already handles case rules. Another is using culture-sensitive comparison for technical identifiers where ordinal matching would be safer. Developers also sometimes forget null handling and then discover the substring check is not the code path that failed; it was the casing call before it.
Summary
- In modern .NET, prefer
Contains(value, StringComparison.OrdinalIgnoreCase). - '
IndexOf(..., StringComparison.OrdinalIgnoreCase) >= 0is a good fallback.' - Avoid
ToLower()andToUpper()as the first choice when a comparison overload exists. - Use ordinal comparison for most technical matching tasks.
- Choose culture-aware comparison only when the text semantics genuinely require it.

