在StringComparison和StringComparer之间转换的优雅方式?

mir*_*lav 8 .net string string-comparison

有些.NET方法使用StringComparison作为参数,有些使用StringComparer(通常采用IComparer的形式).差异很明显.有一些优雅的方法如何从StringComparer获取StringComparison,反之亦然?

我总是可以编写使用Case语句的简单方法,但也许.NET中已经出现了我正在忽略的东西.

Yuv*_*kov 7

没有开箱即用的东西,但您可以在比较和比较器之间创建一个简单的映射:

Dictionary<StringComparison, StringComparer> comparsionToComparer = 
                        new Dictionary<StringComparison, System.StringComparer>
{
    { StringComparison.CurrentCulture, StringComparer.CurrentCulture },
    { StringComparison.CurrentCultureIgnoreCase, StringComparer.CurrentCultureIgnoreCase },
    { StringComparison.InvariantCulture, StringComparer.InvariantCulture },
    { StringComparison.InvariantCultureIgnoreCase, StringComparer.InvariantCultureIgnoreCase },
    { StringComparison.Ordinal, StringComparer.Ordinal },
    { StringComparison.OrdinalIgnoreCase, StringComparer.OrdinalIgnoreCase }
}
Run Code Online (Sandbox Code Playgroud)

什么时候你需要适当的比较器:

var invariantComparer = comparsionToComparer[StringComparsion.InvariantCulture];
Run Code Online (Sandbox Code Playgroud)

编辑:

使用C#-6 Dictionary Initializer语法:

Dictionary<StringComparison, StringComparer> comparsionToComparer = 
                            new Dictionary<StringComparison, System.StringComparer>
{
    [StringComparison.CurrentCulture] = StringComparer.CurrentCulture,
    [StringComparison.CurrentCultureIgnoreCase] = StringComparer.CurrentCultureIgnoreCase,
    [StringComparison.InvariantCulture] = StringComparer.InvariantCulture,
    [StringComparison.InvariantCultureIgnoreCase] = StringComparer.InvariantCultureIgnoreCase,
    [StringComparison.Ordinal] = StringComparer.Ordinal,
    [StringComparison.OrdinalIgnoreCase] = StringComparer.OrdinalIgnoreCase
};
Run Code Online (Sandbox Code Playgroud)

此外,Jons的回答是指线程当前文化的问题,我放弃了它,应该考虑到它


Jon*_*eet 7

从去StringComparisonStringComparer很简单-只需创建一个Dictionary<StringComparison, StringComparer>:

var map = new Dictionary<StringComparison, StringComparer>
{
    { StringComparison.Ordinal, StringComparer.Ordinal },
    // etc
};
Run Code Online (Sandbox Code Playgroud)

有一个StringComparer每一个StringComparison值,所以这样的作品真的很容易.请注意,StringComparer.CurrentCulture取决于当前的线程文化 - 因此,如果您填充字典然后修改线程的文化(或从具有不同文化的不同线程执行),您可能会得到错误的值.你可能想要一个Dictionary<StringComparison, Func<StringComparer>>:

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

然后,您可以通过调用委托随时获得比较器:

var comparer = map[comparison]();
Run Code Online (Sandbox Code Playgroud)

走另一条路是不可行的,因为不是每个人StringComparer 都有一个合适的StringComparison.例如,假设我(在英国)创建一个StringComparer法语(StringComparer.Create(new CultureInfo(..., true)).这StringComparison代表哪个?它对于当前文化,不变文化或序数比较是不正确的.