178

I know that the following is case sensitive:

if (StringA == StringB) {

So is there an operator which will compare two strings in an insensitive manner?

Jon Seigel
  • 12,251
  • 8
  • 58
  • 92
GateKiller
  • 74,180
  • 73
  • 171
  • 204
  • possible duplicate of [Caselessly comparing strings in C#](http://stackoverflow.com/questions/501906/caselessly-comparing-strings-in-c-sharp) – nawfal Jun 06 '13 at 05:40
  • In case someone stumbles across this question looking for a case insensitive comparison for a Dictionary, have a look at this question here: [Case insensitive access for generic dictionary](http://stackoverflow.com/questions/13230414/case-insensitive-access-for-generic-dictionary) – Robotnik Apr 22 '14 at 01:27
  • 1
    It would be really nice; say to define a corresponding `~=` to parallel `==` as a case-insensitive version. – eidylon Sep 11 '17 at 20:42
  • If Microsoft developers see this, I think there is a need for a case-insensitive operator in the next version of csharp. This string.Equal() is lengthy. – Rez.Net Apr 21 '20 at 05:51

13 Answers13

314

Try this:

string.Equals(a, b, StringComparison.CurrentCultureIgnoreCase);
John Feminella
  • 303,634
  • 46
  • 339
  • 357
  • I'm a relative StackOverflow newbie -- can you explain what you mean by adding a link? Do you mean to the MSDN docs? – John Feminella Mar 10 '09 at 16:56
  • You can add an MSDN link (which I usually do) or if you find any interesting blog posts or such that maybe expand the answer. – Samuel Mar 10 '09 at 17:48
  • 1
    And you could enrich your answer by trying to get close to what the asker wanted. In this case, you could post a quick extension method. – Samuel Mar 10 '09 at 17:52
  • 1
    Such as: public static bool EqualsCaseInsensitive(this string a, string b) { return string.Equals(a, b, StringComparison.CurrentCultureIgnoreCase); } – Samuel Mar 10 '09 at 17:55
  • 66
    If you want culture sensitive comparison, use this method. If you just want to make sure "FILE" and "file" are both accepted, use "OrdinalIgnoreCase" or your code might not work in places like Turkish locales. For more info, see http://www.moserware.com/2008/02/does-your-code-pass-turkey-test.html – Jeff Moser Mar 10 '09 at 19:07
  • 5
    Argh this is such an awful mouthful! my keyboard will wear out. Gone are the days when I can use "`if A$=B$ then goto 10`" – Sanjay Manohar Jan 12 '12 at 23:37
  • 12
    @Sanjay Manohar Then write a custom operator - and I'd recommend a better keyboard. – Rushyo Aug 13 '12 at 11:10
  • The extension method is nice, but be aware that LINQ will not expand the extension method and will throw an error if used in a LINQ expression. – Sako73 Dec 21 '15 at 16:52
  • @Sako73 if your default collation in SQL is not a binary one then anytime your LINQ needs to be expanded it is already being evaluated case insensitively. String == string is evaluated by SQL rules not .Net. – Arkaine55 Mar 06 '19 at 13:12
  • May be worth noting that String with a capital S. String.Equals(string, string, StringComparison) – Chase Ernst Oct 21 '19 at 16:08
  • or: a.Equals(b, StringComparison.CurrentCultureIgnoreCase); – Roalt Nov 27 '20 at 10:57
52

The best way to compare 2 strings ignoring the case of the letters is to use the String.Equals static method specifying an ordinal ignore case string comparison. This is also the fastest way, much faster than converting the strings to lower or upper case and comparing them after that.

I tested the performance of both approaches and the ordinal ignore case string comparison was more than 9 times faster! It is also more reliable than converting strings to lower or upper case (check out the Turkish i problem). So always use the String.Equals method to compare strings for equality:

String.Equals(string1, string2, StringComparison.OrdinalIgnoreCase);

If you want to perform a culture specific string comparison you can use the following code:

String.Equals(string1, string2, StringComparison.CurrentCultureIgnoreCase);

Please note that the second example uses the the string comparison logic of the current culture, which makes it slower than the "ordinal ignore case" comparison in the first example, so if you don't need any culture specific string comparison logic and you are after maximum performance, use the "ordinal ignore case" comparison.

For more information, read the full story on my blog.

Pavel Vladov
  • 4,707
  • 3
  • 35
  • 39
  • 2
    Don't suggest `ToLower` or `ToLowerInvariant`: they create memory just to perform a comparison, and they may fail as new character sets are added to unicode. `ToUpper` fails because of the Turkish 'i', among others; there's no reason why `ToLower` won't fail in the future for similar reasons. – antiduh May 15 '15 at 14:21
  • @antiduh, thank you for your comment. Most of us are aware of these potential problems, many tutorials over the Internet give the Turkish 'i' as an example. As you see in my post, I do not recommend using `ToLower` or `ToLowerInvariant` methods, I just wanted to show how much more efficient the `String.Equals` method is. – Pavel Vladov May 18 '15 at 07:06
  • 5
    "Most of us are aware of these potential problems, many tutorials over the Internet give the Turkish 'i' as an example" - not enough people are, and you're still mentioning it as the second sentence in your answer. Furthermore, your *answer* does not include enough justification to never use it - you simply mention performance; performance is not always the ultimate priority. As a result, you're currently violating the help center guidelines; links to external sites are fine, but you've not summarized the content sufficiently (turkish 'i' problem). SO is not your advertising platform. – antiduh May 18 '15 at 13:24
20

There are a number of properties on the StringComparer static class that return comparers for any type of case-sensitivity you might want:

StringComparer Properties

For instance, you can call

StringComparer.CurrentCultureIgnoreCase.Equals(string1, string2)

or

StringComparer.CurrentCultureIgnoreCase.Compare(string1, string2)

It's a bit cleaner than the string.Equals or string.Compare overloads that take a StringComparison argument.

Ryan Lundy
  • 204,559
  • 37
  • 180
  • 211
14
System.Collections.CaseInsensitiveComparer

or

System.StringComparer.OrdinalIgnoreCase
leppie
  • 115,091
  • 17
  • 196
  • 297
9
string.Equals(StringA, StringB, StringComparison.CurrentCultureIgnoreCase);
Erick
  • 5,969
  • 10
  • 42
  • 61
8

or

if (StringA.Equals(StringB, StringComparison.CurrentCultureIgnoreCase)) {

but you need to be sure that StringA is not null. So probably better tu use:

string.Equals(StringA , StringB, StringComparison.CurrentCultureIgnoreCase);

as John suggested

EDIT: corrected the bug

Grzenio
  • 35,875
  • 47
  • 158
  • 240
4

You can use

if (stringA.equals(StringB, StringComparison.CurrentCultureIgnoreCase))
Andy Mikula
  • 16,796
  • 4
  • 32
  • 39
3

Here an idea to simplify the syntax:

public class IgnoreCase
{
    private readonly string _value;

    public IgnoreCase(string s)
    {
        _value = s;
    }

    protected bool Equals(IgnoreCase other)
    {
        return this == other;
    }

    public override bool Equals(object obj)
    {
        return obj != null &&
               (ReferenceEquals(this, obj) || (obj.GetType() == GetType() && this == (IgnoreCase) obj));
    }

    public override int GetHashCode()
    {
        return _value?.GetHashCode() ?? 0;
    }

    public static bool operator ==(IgnoreCase a, IgnoreCase b)
    {
        return string.Equals(a, b, StringComparison.OrdinalIgnoreCase);
    }

    public static bool operator !=(IgnoreCase a, IgnoreCase b)
    {
        return !(a == b);
    }

    public static implicit operator string(IgnoreCase s)
    {
        return s._value;
    }

    public static implicit operator IgnoreCase(string s)
    {
        return new IgnoreCase(s);
    }
}

Usable like:

Console.WriteLine((IgnoreCase) "a" == "b"); // false
Console.WriteLine((IgnoreCase) "abc" == "abC"); // true
Console.WriteLine((IgnoreCase) "Abc" == "aBc"); // true
Console.WriteLine((IgnoreCase) "ABC" == "ABC"); // true
renouve
  • 90
  • 3
  • While I like the clean **looking** usage syntax, it is a bit misleading (`IgnoreCase` vs `IgnoreCaseString`) and ambiguous (Java picks implicit unboxing vs implicit boxing so I _believe_ this wouldn't work in Java with the implicit cast back to string in there). And this creates the memory overhead of 2 new objects with the call tree execution for each comparison jumping into several nested method calls for the displayed usage case. That said, for most cases the performance is probably good enough. – Arkaine55 Mar 06 '19 at 13:01
  • While this is a _clever_ idea, it isn't really wise from a maintainability perspective. You are effectively creating a surrogate string type instead of using the system's built-in string type. The programmer-that-comes-after won't understand what's going on at a glance and then he/she will cuss at you. Using string.Equals() isn't really all that bad and most people will understand what it's doing. – ntcolonel May 22 '20 at 20:17
3

Operator? NO, but I think you can change your culture so that string comparison is not case-sensitive.

// you'll want to change this...
System.Threading.Thread.CurrentThread.CurrentCulture
// and you'll want to custimize this
System.Globalization.CultureInfo.CompareInfo

I'm confident that it will change the way that strings are being compared by the equals operator.

John Leidegren
  • 59,920
  • 20
  • 131
  • 152
  • Yeah, to say the very least it's utterly not what you would want to do unless you want all string comparisons to be case insensitive. But I think it changes the behavior of the equals operator. – John Leidegren Mar 13 '09 at 11:45
1

I am so used to typing at the end of these comparison methods: , StringComparison.

So I made an extension.

namespace System
{   public static class StringExtension
    {
        public static bool Equals(this string thisString, string compareString,
             StringComparison stringComparison)
        {
            return string.Equals(thisString, compareString, stringComparison);
        }
    }
}

Just note that you will need to check for null on thisString prior to calling the ext.

Valamas
  • 24,169
  • 25
  • 107
  • 177
0

Others answer are totally valid here, but somehow it takes some time to type StringComparison.OrdinalIgnoreCase and also using String.Compare.

I've coded simple String extension method, where you could specify if comparison is case sensitive or case senseless with boolean - see following answer:

https://stackoverflow.com/a/49208128/2338477

TarmoPikaro
  • 4,723
  • 2
  • 50
  • 62
0
string.Compare(string1, string2, true)
user25623
  • 245
  • 2
  • 3
-1
if (StringA.ToUpperInvariant() == StringB.ToUpperInvariant()) {

People report ToUpperInvariant() is faster than ToLowerInvariant().

Paul Wicks
  • 62,960
  • 55
  • 119
  • 146
knoopx
  • 17,089
  • 7
  • 36
  • 41
  • 1
    Invariant might be a bad idea if the current or desired culture has special rules for upper-casing. – OregonGhost Mar 10 '09 at 16:56
  • Does this create a new copy of each string? If so, bad idea. – cjk Mar 10 '09 at 17:00
  • 1
    This will also throw an exception if either (or both) strings are null. – tvanfosson Mar 10 '09 at 17:01
  • 3
    Performance-wise, this is not such a good solution as you will create 2 new string instances here as well. – Frederik Gheysels Mar 13 '09 at 09:48
  • as mentioned in multiple comments - don't change the string to upper/lower to compare. just use the existing overload of String.Equals that takes the StringCompare parameter. Your option will be significantly less performant. – Thiago Silva Jul 21 '22 at 23:19