Case Insensitive String Comparison is Teh Suck

Why is it so verbose to compare two strings in C# and see if they are equal, while ignoring case?

What I mean is this:  ("Apples" == "apples")  => false

Take the following examples, each of which does what I want it to, however there is so much noise code here that it really takes away from the readability of the code:

Assert.That(matches[0].Email.Equals(email, StringComparison.InvariantCultureIgnoreCase));
Assert.That(matches[0].Email.ToLower().Equals(email.ToLower()));
Assert.That(string.Compare(matches[0].Email, email) == 0);
Assert.That(Regex.Match(matches[0].Email, email, RegexOptions.IgnoreCase).Success);

Each one of these works, but I really wish this was a language feature.  Wouldn't it be nice to have a new operator syntax?
Assert.That(matches[0].Email ==? email);
//or
Assert.That(matches[0].Email ==~ email);
It turns out that we're not alone.  Ruby and Python have the same problem, however their regular expressions option is much more elegant looking (due to the languages having regex as a core feature).  This seems like such a common need that I'm surprised that this type of thing isn't built into the core of most languages.

Granted, there are concerns about how each one of these would behave, for example, how do you compare strings from two different cultures?  In my case I'm always dealing with English characters, but I fully understand the need to support internationalization.

What do you think?  Would you welcome a new operator to save your self some typing and improve readability?

#1 Will Shaver avatar
Will Shaver
2.29.2008
11:48 AM

You could always do some extension method...public static bool iEquals(this string source, string value){return source.ToLowerInvariant() == value.ToLowerInvariant();}string s = "Bob";string s2 = "boB";Assert.IsTrue(s.iEquals(s2));But yes, I agree that a built in solution would be great.


#2 Peter avatar
Peter
2.29.2008
12:06 PM

Don't forget our good friend PowerShell:--1# "awesomeness" -eq "AWESOMENESS"True--Out of the box! Huzzah!Then, if you actually WANT case sensitivity:--2# "awesomeness" -ceq "AWESOMENESS"False--Huzzah again!Of course, most of you by this point are clawing at your eyes trying to 'un-see' the -eq operator--yes, PowerShell inherits its comparison syntax from the "test" command in unix systems (thanks Bruce Payette/PowerShell in Action for that tidbit). Instead of == or =, you use -eq. So there's both a positive, and a "not positive" aspect of doing comparisons in PowerShell.


#3 David Mohundro avatar
David Mohundro
2.29.2008
12:13 PM

Completely agree - I'm not positive about how I would prefer the syntax, but there is so much line noise when working with strings. I've started learning some Python and Ruby and it just pains me to go back to the verbosity of C#/VB.NET.(PowerShell FTW Peter!)


#4 Aaron Lerch avatar
Aaron Lerch
2.29.2008
2:00 PM

I'm torn on stuff like this. On the one hand, quick and easy language syntax for the most common operation is nice. But on the other hand it can often be an "enabler" for bad code.String comparison is complex enough of an issue that I tend to think that it should be fairly explicit (and thus typically more verbose).Here's a good write-up of some potential issues you can run into without realizing it.http://www.moserware.com/2008/02/does-your-code-pass-turkey-test.html


#5 James Thigpen avatar
James Thigpen
2.29.2008
5:16 PM

String comparisons have always annoyed me.You almost never want what the default is.


#6 Mohammad Azam avatar
Mohammad Azam
3.01.2008
1:21 AM

I agree with Will Shaver! Extension Methods can solve this problem. public static class ExtensionMethods{public static bool BetterEquals(this string strA,string strB){if ((strA == null) && (strB != null)) return false;return strA.Equals(strB, StringComparison.OrdinalIgnoreCase);}}


#7 Ben Scheirman avatar
Ben Scheirman
3.01.2008
12:29 PM

Yes, that works in 2008.Unfortunately I'm still using 2005.I'd settle for something like:string name1 = "BoB";string name2 = "bob";name1.EquivalentTo(name2) => trueor something along those lines.The same thing would also be nice to have for the other string functions like .EndsWith().StartsWith(), etc.


#8 Andy Stopford avatar
Andy Stopford
3.03.2008
2:02 PM

Ben,Both NUnit and MbUnits string asserts will match caseMbUnitStringAssert.EqualsNUnitStringAssert.ContainsUnless in both frameworks you say otherwise with StringAssert.AreEqualIgnoreCaseOf course it's not a constraint but the frameworks with out clutter will allow you to do what you ask.


#9 tgmdbm avatar
tgmdbm
3.23.2008
2:47 PM

you could always use the NUnit Syntax Helpers. Assert.That( a, Is.EqualTo( b ).IgnoreCase );