【问题标题】:Elegant way of converting between StringComparison and StringComparer?在 StringComparison 和 StringComparer 之间转换的优雅方式?
【发布时间】:2015-09-24 14:25:33
【问题描述】:

一些.NET方法使用StringComparison作为参数,一些使用StringComparer(通常以IComparer的形式)。区别很明显。是否有一些优雅的方法可以从 StringComparer 获取 StringComparison 或反之亦然?

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

【问题讨论】:

    标签: .net string string-comparison


    【解决方案1】:

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

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

    每个StringComparison 值都有一个StringComparer,所以这种方式很容易工作。请注意,StringComparer.CurrentCulture 取决于当前的线程文化 - 因此,如果您填充字典然后修改线程的文化(或从具有不同文化的不同线程进行),您最终可能会得到错误的值。你可能想要Dictionary&lt;StringComparison, Func&lt;StringComparer&gt;&gt;:

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

    然后你可以随时通过调用委托来获取比较器:

    var comparer = map[comparison]();
    

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

    【讨论】:

    • 感谢您展示“动态映射”在文化可能发生变化的情况下很有用。或许我也理解为什么 .NET 会开箱即用地提供它。
    【解决方案2】:

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

    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<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 的问题,我放弃了,应该考虑一下

    【讨论】:

    • 是的,这基本上就是我要做的。在编码之前,我在问 .NET 内部是否已经有了类似的东西。
    • @miroxlav 据我所知,没有现有的映射。
    • 根据乔恩的回答,我想我可能明白为什么没有这样的东西。它可能并不像第一眼看上去那么简单。
    • @miroxlav 这并不太难,但我同意这件事可能很难做到。
    【解决方案3】:

    版本基于接受的答案(和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)()
    

    【讨论】:

      【解决方案4】:
          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");
          }
      

      【讨论】:

        【解决方案5】:

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

        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();
          }
        }
        

        【讨论】:

          猜你喜欢
          • 2021-06-30
          • 1970-01-01
          • 2022-12-20
          • 1970-01-01
          • 2015-04-18
          • 1970-01-01
          • 2022-01-19
          • 2013-06-03
          • 1970-01-01
          相关资源
          最近更新 更多