Elegant way of converting between StringComparison and StringComparer?

前端 未结 5 1209
醉梦人生
醉梦人生 2021-01-18 02:49

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

相关标签:
5条回答
  • 2021-01-18 03:13

    There isn't something out of the box, but you can create a simple mapping yourself between the comparsion and the comparer:

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

    And when-ever you need the proper comparer:

    var invariantComparer = comparsionToComparer[StringComparsion.InvariantCulture];
    

    Edit:

    With C#-6 Dictionary Initializer syntax:

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

    Also, Jons answer refers to the issue of the threads current-culture, which i discarded and should probably be taken into account

    0 讨论(0)
  • 2021-01-18 03:20

    vb.net version based on accepted answer (and 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}
        }
    

    Usage:

    Dim comparer As StringComparer = map(comparison)()
    
    0 讨论(0)
  • 2021-01-18 03:24

    An a complete extension method for any one who needs quick copy+paste:

    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 讨论(0)
  • 2021-01-18 03:27
        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");
        }
    
    0 讨论(0)
  • 2021-01-18 03:28

    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.

    0 讨论(0)
提交回复
热议问题