Question
In C#, how can I make string.Contains(...) return true without matching letter casing?
For example:
string title = "ASTRINGTOTEST";
bool result = title.Contains("string");
I want this to evaluate to true, even though the casing is different.
There does not appear to be an overload in older code examples that lets me control case sensitivity directly. Right now, one workaround is to convert both strings to uppercase before comparing, but that approach feels wrong because of internationalization and culture-related casing issues.
Short Answer
By the end of this page, you will understand how case-insensitive substring checks work in C#, why simple uppercasing/lowercasing can be risky, and how to use StringComparison or related APIs to perform safer and clearer string searches.
Concept
String comparison is not as simple as checking whether characters look the same. In programming, case-sensitive comparison treats "A" and "a" as different, while case-insensitive comparison treats them as equal.
When you call Contains on a string, you are asking: “Does this larger string include this smaller string?” The important detail is how the comparison is performed.
In C#, string comparisons can be done in different ways:
- Ordinal: compares raw character values
- OrdinalIgnoreCase: compares raw character values, ignoring case
- CurrentCulture: compares using the current culture's language rules
- CurrentCultureIgnoreCase: same, but ignores case
- InvariantCulture /
InvariantCultureIgnoreCase: culture-aware using invariant rules
This matters because converting both strings with ToUpper() or ToLower() may produce unexpected results in some languages. For example, casing rules differ across cultures, so a manual casing workaround can be less reliable than using the built-in comparison options.
For most programming tasks such as keys, file-like identifiers, protocol values, tags, or technical text matching, StringComparison.OrdinalIgnoreCase is usually the best choice because it is explicit, predictable, and culture-safe for non-linguistic matching.
Mental Model
Think of string searching like checking names on labels.
- A case-sensitive search is like requiring the label to match exactly, including uppercase and lowercase letters.
- A case-insensitive search is like saying, “I only care about the letters, not whether they were written in capitals.”
Now imagine doing this in different countries where letter rules can change. If you manually rewrite every label to uppercase first, you may accidentally change the meaning of some letters. Using StringComparison is like telling C#: “Search using these exact matching rules,” instead of rewriting the text yourself first.
Syntax and Examples
In modern C#, the clearest way is to use the overload of Contains that accepts a StringComparison value:
string title = "ASTRINGTOTEST";
bool result = title.Contains("string", StringComparison.OrdinalIgnoreCase);
Console.WriteLine(result); // True
Why this works
titleis the full string"string"is the substring to search forStringComparison.OrdinalIgnoreCasetells C# to ignore casing during the comparison
Another common option
If you are working in older frameworks where that overload is not available, use IndexOf:
string title = "ASTRINGTOTEST";
bool result = title.IndexOf("string", StringComparison.OrdinalIgnoreCase) >= 0;
Console.WriteLine(result); // True
Example with user input
string message = "Welcome To Production";
search = ;
(message.Contains(search, StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine();
}
Step by Step Execution
Consider this example:
string title = "ASTRINGTOTEST";
bool found = title.Contains("string", StringComparison.OrdinalIgnoreCase);
Console.WriteLine(found);
Here is what happens step by step:
titleis assigned the value"ASTRINGTOTEST".- C# searches inside that string for the substring
"string". - Because
StringComparison.OrdinalIgnoreCaseis used, C# ignores uppercase/lowercase differences. - It checks whether the sequence of letters
s t r i n gappears intitle. "ASTRINGTOTEST"contains"STRING", which matches"string"when case is ignored.- So
foundbecomestrue. Console.WriteLine(found);printsTrue.
Traceable example with a non-match
title = ;
found = title.Contains(, StringComparison.OrdinalIgnoreCase);
Console.WriteLine(found);
Real World Use Cases
Case-insensitive substring matching is very common in real programs.
Search boxes
A user searches for report, but your stored title is MonthlyReport2024.
title.Contains("report", StringComparison.OrdinalIgnoreCase)
Filtering logs
You want to detect log entries containing error, warning, or timeout regardless of casing.
logLine.Contains("error", StringComparison.OrdinalIgnoreCase)
API parameter checks
A query string or header may contain values in unpredictable casing.
if (headerValue.Contains("json", StringComparison.OrdinalIgnoreCase))
{
// Handle JSON response
}
Command parsing
A command-line app may accept commands like START, Start, or start.
Real Codebase Usage
In real codebases, developers usually avoid manual casing conversions and instead choose an explicit comparison strategy.
Common pattern: validation before searching
if (string.IsNullOrEmpty(title))
return false;
return title.Contains(searchText, StringComparison.OrdinalIgnoreCase);
This uses a guard clause to avoid errors or pointless checks.
Common pattern: fallback for older frameworks
return title?.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) >= 0;
This is common in legacy code where Contains(..., StringComparison) is unavailable.
Common pattern: filtering collections
var matches = products
.Where(p => p.Name.Contains("pro", StringComparison.OrdinalIgnoreCase))
.ToList();
This is typical in search, reporting, or admin tools.
Common pattern: early return
if (string.IsNullOrWhiteSpace(searchText))
return items;
If there is nothing to search for, return early instead of doing unnecessary work.
Common Mistakes
1. Converting both strings to uppercase or lowercase
This works sometimes, but it is not the best default approach.
// Less ideal
bool result = title.ToUpper().Contains(search.ToUpper());
Why to avoid it:
- extra string allocations
- less clear intent
- culture-related casing issues
Prefer:
bool result = title.Contains(search, StringComparison.OrdinalIgnoreCase);
2. Forgetting null checks
This will throw if title is null.
string title = null;
bool result = title.Contains("test", StringComparison.OrdinalIgnoreCase); // Error
Safer version:
bool result = title?.Contains("test", StringComparison.OrdinalIgnoreCase) == true;
3. Using the wrong comparison type
Beginners often use culture-aware comparison when they actually want technical matching.
Comparisons
| Approach | Example | Case-insensitive | Recommended? | Notes |
|---|---|---|---|---|
Contains("text") | title.Contains("string") | No | Sometimes | Simple, but case-sensitive |
Contains("text", StringComparison.OrdinalIgnoreCase) | title.Contains("string", StringComparison.OrdinalIgnoreCase) | Yes | Yes | Best modern option |
IndexOf(..., StringComparison) >= 0 | title.IndexOf("string", StringComparison.OrdinalIgnoreCase) >= 0 | Yes | Yes | Great fallback for older frameworks |
Cheat Sheet
// Best modern option
text.Contains(value, StringComparison.OrdinalIgnoreCase)
// Older framework fallback
text.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0
Quick rules
Contains("text")is case-sensitive.- Use
StringComparison.OrdinalIgnoreCasefor most technical matching. - Avoid
ToUpper()/ToLower()as your default solution. - Use
CurrentCultureIgnoreCaseonly when language-specific user text matters. - If
textmay benull, use null-safe checks.
Null-safe example
bool found = text?.Contains("abc", StringComparison.OrdinalIgnoreCase) == true;
Older .NET example
bool found = text?.IndexOf("abc", StringComparison.OrdinalIgnoreCase) >= 0;
Remember
FAQ
How do I make Contains case-insensitive in C#?
Use:
text.Contains(value, StringComparison.OrdinalIgnoreCase)
What should I use if my .NET version does not support that overload?
Use IndexOf:
text.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0
Why is ToUpper() or ToLower() not the best approach?
Because it can create unnecessary new strings and may behave unexpectedly with culture-specific casing rules.
Should I use OrdinalIgnoreCase or CurrentCultureIgnoreCase?
Use OrdinalIgnoreCase for most technical comparisons. Use CurrentCultureIgnoreCase when matching user-facing natural language text.
Does case-insensitive search ignore spelling differences?
No. It only ignores uppercase/lowercase differences.
Can Contains throw an exception?
Yes. If the source string is , calling on it will fail. Use a null check or null-conditional operator.
Mini Project
Description
Build a simple C# console program that filters a list of article titles using a case-insensitive search term. This demonstrates how substring searching works in realistic code where user input may have different capitalization from stored data.
Goal
Create a program that prints all titles containing a search term, regardless of letter casing.
Requirements
- Create a list of at least five string titles.
- Ask the user to enter a search term.
- Print only the titles that contain the search term.
- Make the search case-insensitive.
- Handle empty input safely.
Keep learning
Related questions
AddTransient vs AddScoped vs AddSingleton in ASP.NET Core Dependency Injection
Learn the differences between AddTransient, AddScoped, and AddSingleton in ASP.NET Core DI with examples and practical usage.
C# Type Checking Explained: typeof vs GetType() vs is
Learn when to use typeof, GetType(), and is in C#. Understand exact type checks, inheritance, and safe type testing clearly.
C# Version Numbers Explained: C# vs .NET Framework and Why “C# 3.5” Is Incorrect
Learn the correct C# version numbers, how they map to .NET releases, and why terms like C# 3.5 are inaccurate and confusing.