Array
Case-Insensitive
String Array
Programming
Coding

How can I make Array.Contains case-insensitive on a string array?

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

Introduction

Array.Contains on strings is case-sensitive by default because it uses the default equality comparer. If you need case-insensitive matching, the correct solution is choosing the right comparer explicitly rather than normalizing strings ad hoc everywhere. The best approach depends on whether you need one-off lookup, repeated lookup, or culture-aware matching.

Use LINQ With a String Comparer

For a simple one-off check, use Enumerable.Contains with a comparer.

csharp
1using System;
2using System.Linq;
3
4class Program
5{
6    static void Main()
7    {
8        string[] values = { "Alpha", "Bravo", "Charlie" };
9
10        bool found = values.Contains("bravo", StringComparer.OrdinalIgnoreCase);
11        Console.WriteLine(found);
12    }
13}

StringComparer.OrdinalIgnoreCase is usually the right default for identifiers, codes, and protocol-style strings.

Why OrdinalIgnoreCase Is Usually Best

There are several comparison modes in .NET. The two common ones here are:

  • 'StringComparer.OrdinalIgnoreCase'
  • 'StringComparer.CurrentCultureIgnoreCase'

Use OrdinalIgnoreCase when comparison is technical rather than linguistic. It is predictable and usually faster.

csharp
bool found = values.Contains("BRAVO", StringComparer.OrdinalIgnoreCase);

Use culture-aware comparison only when user-facing linguistic behavior actually matters.

Avoid Manual ToLower() and ToUpper()

A common workaround is normalizing both sides with ToLowerInvariant() or ToUpperInvariant(). That works, but it creates extra strings and spreads comparison policy across the codebase.

Less desirable approach:

csharp
bool found = values.Any(x => x.ToLowerInvariant() == "bravo".ToLowerInvariant());

Cleaner approach:

csharp
bool found = values.Contains("bravo", StringComparer.OrdinalIgnoreCase);

The comparer-based version is clearer and avoids unnecessary allocations.

Repeated Lookups: Use a HashSet<string>

If you need many case-insensitive lookups, convert the array into a HashSet<string> with the right comparer.

csharp
1using System;
2using System.Collections.Generic;
3
4class Program
5{
6    static void Main()
7    {
8        string[] values = { "Alpha", "Bravo", "Charlie" };
9        var set = new HashSet<string>(values, StringComparer.OrdinalIgnoreCase);
10
11        Console.WriteLine(set.Contains("bravo"));
12        Console.WriteLine(set.Contains("CHARLIE"));
13    }
14}

This is much better than repeatedly scanning the whole array if the lookup count is high.

Null Handling

If arrays can contain null, think about the intended behavior. StringComparer handles comparison cleanly, but your surrounding logic still needs to be explicit.

csharp
1using System;
2using System.Linq;
3
4class Program
5{
6    static void Main()
7    {
8        string[] values = { "Alpha", null, "Charlie" };
9
10        bool foundAlpha = values.Contains("alpha", StringComparer.OrdinalIgnoreCase);
11        bool foundNull = values.Any(x => x is null);
12
13        Console.WriteLine(foundAlpha);
14        Console.WriteLine(foundNull);
15    }
16}

Do not assume null semantics are the same as empty string semantics.

Exact Method Choice Matters

There are two different Contains paths developers often confuse:

  • 'Array.IndexOf'
  • LINQ Enumerable.Contains

Array.IndexOf does not accept a comparer for strings in the same convenient way. If you need custom comparison semantics, LINQ is usually the more direct choice.

For more custom matching, Any works well:

csharp
1using System;
2using System.Linq;
3
4bool found = values.Any(x => string.Equals(x, "bravo", StringComparison.OrdinalIgnoreCase));

This is especially useful when additional conditions are needed.

Pick the Right Comparison Rule for the Domain

If strings represent usernames, file extensions, configuration keys, or command names, OrdinalIgnoreCase is usually the safest option. If strings represent human-language text shown to users, evaluate whether culture-aware behavior is actually required.

Do not choose the comparison rule casually. Equality semantics are part of your data contract.

Common Pitfalls

One common mistake is using ToLower() everywhere instead of one explicit comparer-based rule. Another is using culture-aware comparison for non-linguistic identifiers, which can create surprising behavior. Developers also keep arrays for repeated lookups when a HashSet<string> would be more appropriate. Null values are frequently ignored until an edge case appears. Finally, teams often mix different comparison rules in different modules and get inconsistent behavior.

Summary

  • 'Array.Contains on strings is case-sensitive by default.'
  • Use LINQ Contains with StringComparer.OrdinalIgnoreCase for one-off case-insensitive checks.
  • Prefer comparer-based logic over manual case normalization.
  • Use HashSet<string> with a comparer for repeated lookups.
  • Choose comparison semantics based on domain needs, not convenience.
  • Keep null handling and string comparison policy explicit.

Related reading
Course
Intermediate
27 lessons
15 hours
DSA Fundamentals

Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

All Rights Reserved.