Comparing Strings Like It's 1995

Posted on November 13, 2009  |  

Posted in Development

9 comments

While going through The Art of Unit Testing: with Examples in .NET this morning, I came across a string comparison notation, which always makes me cringe:

if (!fileName.ToLower().EndsWith (".slv"))
{
}

I’ve also lost count of seeing its closest cousin:

if (someText.ToLower() === "some test value")
{
}

This is how we used to roll in C++. I’m surprised anybody still does this.

For one, ToLower() doesn’t produce consistent results for several languages, e.g. Turkish (see The Motivation: The Turkish-I Problem).

The other problem is possibly calling ToLower() on a null, so you have to run null checks all over the place. Why not use string.Equals instead? It’s null-friendly.

In .NET, you should do culture-aware comparisons. With FxCop, every time you do otherwise, it will apply its Specify CultureInfo rule:

Because the behavior of ’string.ToLower()’ could vary based on the current user’s locale settings, replace this call in ’Foo()’ with a call to ’string.ToLower(CultureInfo)’. If the result of ’string.ToLower(CultureInfo)’ will be displayed to the user, specify ’CultureInfo.CurrentCulture’ as the ’CultureInfo’ parameter. Otherwise, if the result will be stored and accessed by software, such as when it is persisted to disk or to a database, specify ’CultureInfo.InvariantCulture’.”

Microsoft has an excellent whitepaper on MSDN, New Recommendations for Using Strings in Microsoft .NET 2.0. Read it and memorize it.

9 comments

Rik Hemsley
on November 13, 2009

Not disagreeing, but: How would this be a problem with the file extension comparison?


Milan Negovan
on November 13, 2009

At the very least I'd do this:

fileName.EndsWith (".slv", StringComparison.OrdinalIgnoreCase)


RichB
on November 13, 2009

ToLowerInvariant() is a better choice if you must use ToLower()


roy
on November 14, 2009

so how would you drive such a change through TDD?
ToLower was the simplest in terms of funxtionality


Milan Negovan
on November 14, 2009

The MSDN article I referred to has a section, "What About the Earlier Recommendation for Invariant Culture?", about ToLowerInvariant. Its usage is discourage and kept only for backward compatibility.


net
on November 15, 2009

how about
System.Path.GetFileExtension(fileName) == ".slv"


Milan Negovan
on November 15, 2009

You still make an assumption about casing. And what if it contains non-Latin characters? This is why you need to perform culture-aware comparisons.


nic0428
on November 15, 2009

Its a shame how much "==" string comparison I've used for my .net projects. Thanks for sharing the idea!! The .NET article was great.


rtpHarry
on November 15, 2009

Interesting article. I do usually use .Equals rather than == just to avoid the possibility of accidentally assigning rather than comparing. I wasn't sure if there were any other technical reasons for this.

That book is high on my Christmas wish list as well...


Leave a comment

  •