Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Elegant way of converting between StringComparison and StringComparer?

Some .NET methods use StringComparison as parameter, some use StringComparer (often in form of IComparer). The difference is clear. Is there some elegant way how to get StringComparison from StringComparer or vice versa?

I can always write simple method which uses Case statement, but perhaps there is already something present in .NET what I am overlooking.

like image 924
miroxlav Avatar asked Sep 24 '15 14:09

miroxlav


2 Answers

    public static StringComparer ToComparer(this StringComparison comparison)
    {
        switch (comparison) {
            case StringComparison.CurrentCulture:
                return StringComparer.CurrentCulture;
            case StringComparison.CurrentCultureIgnoreCase:
                return StringComparer.CurrentCultureIgnoreCase;
            case StringComparison.InvariantCulture:
                return StringComparer.InvariantCulture;
            case StringComparison.InvariantCultureIgnoreCase:
                return StringComparer.InvariantCultureIgnoreCase;
            case StringComparison.Ordinal:
                return StringComparer.Ordinal;
            case StringComparison.OrdinalIgnoreCase:
                return StringComparer.OrdinalIgnoreCase;
            default:
                break;
        }

        throw new NotImplementedException("Unknown StringComparison");
    }
like image 124
user3720899 Avatar answered Oct 11 '22 21:10

user3720899


Going from StringComparison to StringComparer is simple - just create a Dictionary<StringComparison, StringComparer>:

var map = new Dictionary<StringComparison, StringComparer>
{
    { StringComparison.Ordinal, StringComparer.Ordinal },
    // etc
};

There is a StringComparer for every StringComparison value, so that way works really easily. Mind you, StringComparer.CurrentCulture depends on the current thread culture - so if you populate the dictionary and then modify the thread's culture (or do it from a different thread with a different culture) you may end up with the wrong value. You potentially want a Dictionary<StringComparison, Func<StringComparer>>:

var map = new Dictionary<StringComparison, Func<StringComparer>>
{
    { StringComparison.Ordinal, () => StringComparer.Ordinal },
    // etc
};

Then you can get a comparer at any time by invoking the delegate:

var comparer = map[comparison]();

Going the other way is infeasible, because not every StringComparer has a suitable StringComparison. For example, suppose I (in the UK) create a StringComparer for French (StringComparer.Create(new CultureInfo(..., true)). Which StringComparison does that represent? It's not correct for the current culture, the invariant culture, or ordinal comparisons.

like image 20
Jon Skeet Avatar answered Oct 11 '22 22:10

Jon Skeet