447

Which of the following two is more efficient? (Or maybe is there a third option that's better still?)

string val = "AStringValue";

if (val.Equals("astringvalue", StringComparison.InvariantCultureIgnoreCase))

OR

if (val.ToLowerCase() == "astringvalue")

?

Samuel Liew
  • 76,741
  • 107
  • 159
  • 260
pwmusic
  • 4,739
  • 4
  • 23
  • 14
  • 15
    I think that's the wrong question. The right question is "Which is these is more correct?" – asawyer Jun 16 '11 at 11:39
  • 2
    there's also if (string.Compare(strA, strB, StringComparison.OrdinalIgnoreCase) == 0) or if (val.Equals("AStringValue", StringComparison.OrdinalIgnoreCase)), Correctness often comes down to personal perference aswell, there more discussion on which method is correct at http://stackoverflow.com/questions/44288/differences-in-string-compare-methods-in-c – Mark Jun 16 '11 at 11:41
  • 5
    @asawyer, why would it be "more correct" rather than "more efficient"? – foxy Jun 16 '11 at 11:42
  • 1
    Jon Skeet has already answered this [here](http://stackoverflow.com/questions/3694863/c-confusion-about-toupper-and-tolower). – Øyvind Bråthen Jun 16 '11 at 11:43
  • I prefer Equals as it is Ronsell (it does what it says on the tin) in one line. ToLowerCase requires reading the line above,combining their logic to work out why you're lowercasing anything. – TinyRacoon Sep 24 '19 at 10:32

8 Answers8

414

If you're looking for efficiency, use this:

string.Equals(val, "astringvalue", StringComparison.OrdinalIgnoreCase)

Ordinal comparisons can be significantly faster than culture-aware comparisons.

ToLowerCase can be the better option if you're doing a lot of comparisons against the same string, however.

As with any performance optimization: measure it, then decide!

Sven
  • 21,903
  • 4
  • 56
  • 63
  • 13
    When calling a static method, I would always use the class name like `String.Equals` with capital 'S', or for example `Int32.Parse` instead of `int.Parse`. Good tip on `OrdinalIgnoreCase`. Thanks. – orad Nov 16 '13 at 01:59
  • Why can ToLowerCase be a better option if comparing a lot against the same string ? By doing this, you'll have to 'tolower' the other string each time, which can be expensive. – Frederik Gheysels Jun 24 '15 at 13:45
  • 1
    @FrederikGheysels I presume Sven is suggesting you store the result of ToLower() in a variable and then perform each of your comparisons against that. – pwdst Sep 10 '15 at 16:28
  • Microsoft seem to suggest that you use ToUpperInvariant instead of ToLower - https://msdn.microsoft.com/en-us/library/dd465121.aspx - for your multiple comparison scenario. In either case, it should probably be an Invariant method. – pwdst Sep 10 '15 at 16:31
  • @pwdst : this means that you have to perform a tolower on each other string that you want to compare against the stored variable as well. – Frederik Gheysels Sep 10 '15 at 19:36
  • 4
    @FrederikGheysels Correct but the documentation for StringComparer.OrdinalIgnoreCase states "The StringComparer returned by the OrdinalIgnoreCase property **treats the characters in the strings to compare as if they were converted to uppercase using the conventions of the invariant culture**, and then performs a simple byte comparison that is independent of language." (see https://msdn.microsoft.com/en-us/library/system.stringcomparer.ordinalignorecase.aspx). If you can store the result of the left side of the comparison then work only needs to be done on the right. – pwdst Sep 11 '15 at 12:21
  • @FrederikGheysels So for *many* comparisons storing ToUpperInvariant on the comparison value **may** perform better than using OrdinalIgnore call for each comparison. In either case you should probably use String.Equals and explicitly state the comparison. As always, if in doubt - measure. – pwdst Sep 11 '15 at 12:24
  • 1
    @orad Could you explain why that's preferred/better? – ErroneousFatality Dec 16 '21 at 17:24
  • @ErroneousFatality I prefer to use primitive type aliases (int, short, string, ...) only for the purpose of defining types, not for anything else. Otherwise, you could also use them to access the type's constructor such as `new string('a', 10)` which does not follow .NET naming conventions. – orad Dec 17 '21 at 18:57
216

The first one is the correct one, and IMHO the more efficient one, since the second 'solution' instantiates a new string instance.

wonea
  • 4,783
  • 17
  • 86
  • 139
Frederik Gheysels
  • 56,135
  • 11
  • 101
  • 154
  • 15
    But efficiency aside, I see far more usage of the second solution because it works, is shorter and easier to type, and has an easy-to-remember, straight-forward format. "StringComparison.InvariantCultureIgnoreCase"...really? – BengalTigger Aug 29 '16 at 19:00
  • 1
    @BengalTigger At the very least, the second example should be using `ToLowerInvariant()`. But, the first one may well instantiate two new string instances, so it's not necessarily faster. – jpaugh Jun 13 '17 at 17:31
50

The .ToLowerCase version is not going to be faster - it involves an extra string allocation (which must later be collected), etc.

Personally, I'd use

string.Equals(val, "astringvalue",  StringComparison.OrdinalIgnoreCase)

this avoids all the issues of culture-sensitive strings, but as a consequence it avoids all the issues of culture-sensitive strings. Only you know whether that is OK in your context.

Using the string.Equals static method avoids any issues with val being null.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • 3
    Can you tell us that why do you use StringComparison.OrdinalIgnoreCase instead of StringComparison.InvariantCultureIgnoreCase? – mqpasta Jun 16 '11 at 11:46
  • 3
    @mqpasta - it depends on the purpose, of course, but http://msdn.microsoft.com/en-us/library/system.stringcomparer.ordinalignorecase.aspx "This is most appropriate when comparing strings that are generated programmatically or when comparing case-insensitive resources such as paths and filenames." - plus, it is a tiny bit faster – Marc Gravell Jun 16 '11 at 11:48
  • @mqpasta: Ordinalignorecase is more efficient than Invariantcultureignorecase. – Tim Schmelter Jul 08 '22 at 17:24
14

My general answer to this kind of question on "efficiency" is almost always, which ever version of the code is most readable, is the most efficient.

That being said, I think (val.ToLowerCase() == "astringvalue") is pretty understandable at a glance by most people.

The efficience I refer to is not necesseraly in the execution of the code but rather in the maintanance and generally readability of the code in question.

Jamie Dixon
  • 53,019
  • 19
  • 125
  • 162
  • 1
    Using `Equals` with `StringComparison.OrdinalIgnoreCase` is quite as readable and way less error-prone, especially for string literals like in the example above. You may even create an extensions method `EqualsIgnoreCase` that internally decides which `StringComparison` to use. – Lukas Körfer Apr 06 '22 at 10:21
9

I'd venture that the safest is to use the static method String.Equals to mitigate against the possibility of a NullReferenceException in the case that val is null.

spender
  • 117,338
  • 33
  • 229
  • 351
6

The former is fastest. Turns out that val is immutable, and so a new string object is created with String.ToLowerCase(), rather than just direct comparison with the string comparer. Creating a new string object can be costly if you're doing this many times a second.

foxy
  • 7,599
  • 2
  • 30
  • 34
3

you may also want to look at that already answered question Differences in string compare methods in C#

Community
  • 1
  • 1
Tomasz Jaskuλa
  • 15,723
  • 5
  • 46
  • 73
2

1st is more efficient (and the best possible option) because val.ToLowerCase() creates a new object since Strings are immutable.

Ruslan
  • 9,927
  • 15
  • 55
  • 89