.net 在StringComparison和StringComparer之间转换的优雅方法?

js5cn81o  于 2023-02-10  发布在  .NET
关注(0)|答案(6)|浏览(94)

有些.NET方法使用StringComparison作为参数,有些使用StringComparer(通常以IComparer的形式)。区别很明显。有没有什么优雅的方法可以从StringComparer获得StringComparison,反之亦然?
我总是可以编写使用Case语句的简单方法,但也许在.NET中已经存在一些我忽略的东西。

avwztpqn

avwztpqn1#

StringComparison升级到StringComparer非常简单-只需创建一个Dictionary<StringComparison, StringComparer>

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

每个StringComparison值都有一个StringComparer,所以这种方法很容易实现。请注意,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.Create(new CultureInfo(..., true))创建了一个StringComparer。这表示哪个StringComparison?它对于当前区域性、不变区域性或序号比较都不正确。

h9vpoimq

h9vpoimq2#

没有现成的东西,但是您可以自己在比较和比较器之间创建一个简单的Map:

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的问题,我已将其丢弃,可能应该将其考虑在内

dxpyg8gm

dxpyg8gm3#

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

xkftehaa4#

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");
    }
isr3a4wc

isr3a4wc5#

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

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

rggaifut6#

对于.NET Core 2.0或更高版本以及.NET Standard 2.1,您可以使用

public static StringComparer FromComparison(StringComparison comparisonType);

https://learn.microsoft.com/en-us/dotnet/api/system.stringcomparer.fromcomparison

相关问题