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

问题描述 投票:7回答:5

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

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

.net string string-comparison
5个回答
6
投票

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

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

每个StringComparer值都有一个StringComparison,所以这种方式非常容易。请注意,StringComparer.CurrentCulture依赖于当前的线程文化 - 因此,如果您填充字典然后修改线程的文化(或者从具有不同文化的不同线程执行此操作),您可能会得到错误的值。你可能想要一个Dictionary<StringComparison, Func<StringComparer>>

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

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

var comparer = map[comparison]();

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


6
投票

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

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 }
}

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

var invariantComparer = comparsionToComparer[StringComparsion.InvariantCulture];

编辑:

使用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
};

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


1
投票

版本基于已接受的答案(和Option Infer Off):

Dim map As New Dictionary(Of StringComparison, Func(Of StringComparer))() _
    From {
        {StringComparison.CurrentCulture, Function() StringComparer.CurrentCulture},
        {StringComparison.CurrentCultureIgnoreCase, Function() StringComparer.CurrentCultureIgnoreCase},
        {StringComparison.InvariantCulture, Function() StringComparer.InvariantCulture},
        {StringComparison.InvariantCultureIgnoreCase, Function() StringComparer.InvariantCultureIgnoreCase},
        {StringComparison.Ordinal, Function() StringComparer.Ordinal},
        {StringComparison.OrdinalIgnoreCase, Function() StringComparer.OrdinalIgnoreCase}
    }

用法:

Dim comparer As StringComparer = map(comparison)()

0
投票

对于需要快速复制+粘贴的任何人来说,这是一个完整的扩展方法:

public static class StringComparisonExtensions
{
  // from http://stackoverflow.com/a/32764112/548304
  private static readonly Dictionary<StringComparison, Func<StringComparer>> ComparsionToComparer =
    new Dictionary<StringComparison, Func<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
      };

  /// <summary>
  ///  Retrieves a string comparer for the given StringComparison.
  /// </summary>
  public static StringComparer ToComparer(this StringComparison comparison)
  {
    return ComparsionToComparer.GetValueOrDefault(comparison)?.Invoke();
  }
}

0
投票
    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");
    }
© www.soinside.com 2019 - 2024. All rights reserved.