string

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.

csharp
1using System;
2
3string text = "Hello World";
4bool found = text.Contains("world", StringComparison.OrdinalIgnoreCase);
5
6Console.WriteLine(found);

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.

csharp
1using System;
2
3string text = "Hello World";
4bool found = text.IndexOf("world", StringComparison.OrdinalIgnoreCase) >= 0;
5
6Console.WriteLine(found);

This is historically common and still perfectly valid.

Why ToLower() Is Not the Best First Choice

A lot of examples use this pattern:

csharp
bool found = text.ToLower().Contains(search.ToLower());

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.

csharp
1using System;
2
3string? text = "Hello World";
4string? search = "world";
5
6bool found = text?.Contains(search ?? string.Empty, StringComparison.OrdinalIgnoreCase) ?? false;
7Console.WriteLine(found);

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.

csharp
bool found = text.Contains(search, StringComparison.CurrentCultureIgnoreCase);

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) >= 0 is a good fallback.'
  • Avoid ToLower() and ToUpper() 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.

Course illustration
Course illustration

All Rights Reserved.