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

时间:2015-09-24 14:25:33

标签: .net string string-comparison

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

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

5 个答案:

答案 0 :(得分: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指的是线程current-culture的问题,我放弃了它,应该考虑到它

答案 1 :(得分:6)

StringComparison转到StringComparer很简单 - 只需创建一个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代表什么?它对于当前文化不正确,不变量文化或序数比较。

答案 2 :(得分: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)()

答案 3 :(得分: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();
  }
}

答案 4 :(得分: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");
    }