1

In the simple method below, for string comparers I'm calling corresponding ToLower() methods. Is there case conversion method for StringComparer.OrdinalIgnoreCase exposed somewhere in the framework?

Function ToLowerIfCaseInsensitiveComparison(s As String, cmp As StringComparison) As String
    Select Case cmp
        Case StringComparison.CurrentCultureIgnoreCase
            Return s.ToLower()
        Case StringComparison.InvariantCultureIgnoreCase
            Return s.ToLowerInvariant()
        Case StringComparison.OrdinalIgnoreCase
            Return ___________________ ' expecting your answers
        Case Else
            Return s
    End Select
End Function

(C# or VB – whatever you prefer. The answer probably won't be language-dependent anyway.)


UPDATE: I have to correct myself regarding lowercase conversion: Best Practices for Using Strings in the .NET Framework says that

Use the String.ToUpperInvariant method instead of the String.ToLowerInvariant method when you normalize strings for comparison.

miroxlav
  • 11,796
  • 5
  • 58
  • 99
  • 1
    This sounds like an [XY problem](http://meta.stackexchange.com/q/66377/147640). – GSerg Sep 12 '15 at 11:18
  • Also you might find [Upper vs Lower Case](http://stackoverflow.com/q/234591/11683) and [C#: Confusion about ToUpper() and ToLower()](http://stackoverflow.com/q/3694863/11683) useful. – GSerg Sep 12 '15 at 11:21

1 Answers1

2

StringComparison.OrdinalIgnoreCase can be used as a parameter for string.Equals, to save you have to using ToLower to remove case sensitivity in your comparison.

In C#:

var string1 = "Hello";
var string2 = "hello";

Console.WriteLine(string1.Equals(string2, StringComparison.OrdinalIgnoreCase));

// Output: true

An Ordinal comparison is based on the numeric value (Unicode code point) of each Char in the string. If you want to return the string in a format for ordinal comparison you could use this method:

string GetUnicodeString(string s)
{
    StringBuilder sb = new StringBuilder();
    foreach (char c in s)
    {
        sb.Append("\\u");
        sb.Append(String.Format("{0:x4}", (int)c));
    }
    return sb.ToString();
}
Glen Thomas
  • 10,190
  • 5
  • 33
  • 65
  • I prefer `string.Compare` - for clarity and for added benefit of being able to compare `null` strings. – GSerg Sep 12 '15 at 11:23
  • I'm not familiar with Compare. That could come in useful – Glen Thomas Sep 12 '15 at 11:26
  • 1
    @miroxlav I don't understand what you mean – Glen Thomas Sep 12 '15 at 11:27
  • 1
    @GSerg – `String.Equals()` is recommended for *comparison* while `String.Compare()` is recommended for *sorting* – see [Best Practices for Using Strings in the .NET Framework](https://msdn.microsoft.com/en-us/library/vstudio/dd465121.aspx). They seem to explicitly discourage using the latter for string comparison, I quote: *Do not use an overload of the **String.Compare** or **CompareTo** method and test for a return value of zero to determine whether two strings are equal.* – miroxlav Sep 14 '15 at 06:51
  • @miroxlav Okay, that notice seems to have appeared for .NET 4.0 and up. I was not aware of it, and I now wonder why it exists and why it makes a difference. – GSerg Sep 14 '15 at 08:19
  • @GSerg – they use different default comparison. `string.Equals()` (equivalent to `==` in case of strings) uses *Ordinal* (binary) comparison, while `string.CompareTo()` uses *CurrentCulture*. Although that article recommends *always* providing the comparison *explicitly*, if you use implicit one, then *Ordinal* (binary) comparison would be probably expected by most developers who want to determine whether strings are *equal*. Thus this speaks against `string.CompareTo()` and in favor of `string.Equals()`. – miroxlav Sep 14 '15 at 08:48
  • @miroxlav I never use implicit ones, so I really wonder why `if (string.Compare(s1, s2, StringComparison.OrdinalIgnoreCase) == 0)` is bad and `if (s1.Equals(s2, StringComparison.OrdinalIgnoreCase))` is not. In my opinion the former is better because it won't explode when `s1` is `null`. – GSerg Sep 14 '15 at 09:09
  • @GSerg – I wonder why odd&obsolete C-language practice has a place in .NET (except of reason that you set some custom standards for your project...) but that's different topic and I do not want to make long discussions here. Of course, if you are not having `null`s under control, then I understand that you need to apply a workaround. In your shoes, I would add extension method for Equals, handling nulls gracefully. – miroxlav Sep 14 '15 at 09:27
  • It's just sometimes people who write content for MSDN make mistakes, so one has to be aware. [static int Compare](http://referencesource.microsoft.com/mscorlib/R/0be9474bc8e160b6.html) has the same internals as [public bool Equals](http://referencesource.microsoft.com/mscorlib/R/b98069ccbe2d3960.html), and is referenced thousands of times from the internals of .NET framework in the form of `if (string.Compare() == 0)`. – GSerg Sep 14 '15 at 10:12
  • The only difference is that for the `Ordinal` comparison, `Compare` calls [CompareOrdinalHelper](http://referencesource.microsoft.com/mscorlib/R/8711fff131bc4d0e.html) and `Equals` calls [EqualsHelper](http://referencesource.microsoft.com/mscorlib/R/11648d2d83718c5e.html), and the latter appears to be a tiny fraction faster in its `unsafe` code because it does not have to tell if the first string is greater or less than the second, only that they are equal or not. – GSerg Sep 14 '15 at 10:15