在 StringComparison 和 StringComparer 之间转换的优雅方式?
Elegant way of converting between StringComparison and StringComparer?
一些 .NET 方法使用 StringComparison as parameter, some use StringComparer (often in form of IComparer)。区别很明显。是否有一些优雅的方法如何从 StringComparer 获取 StringComparison 或者反之亦然?
我总是可以编写使用 Case
语句的简单方法,但也许 .NET 中已经存在一些我忽略的东西。
没有开箱即用的东西,但您可以自己在比较器和比较器之间创建一个简单的映射:
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
};
此外, 指的是线程当前文化的问题,我已将其丢弃,应该予以考虑
从 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
(StringComparer.Create(new CultureInfo(..., true))
。那代表哪个 StringComparison
?这对当前文化、不变文化或序数不正确比较。
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)()
一个完整的扩展方法,适合任何需要快速复制+粘贴的人:
public static class StringComparisonExtensions
{
// from
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();
}
}
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");
}
一些 .NET 方法使用 StringComparison as parameter, some use StringComparer (often in form of IComparer)。区别很明显。是否有一些优雅的方法如何从 StringComparer 获取 StringComparison 或者反之亦然?
我总是可以编写使用 Case
语句的简单方法,但也许 .NET 中已经存在一些我忽略的东西。
没有开箱即用的东西,但您可以自己在比较器和比较器之间创建一个简单的映射:
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
};
此外,
从 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
(StringComparer.Create(new CultureInfo(..., true))
。那代表哪个 StringComparison
?这对当前文化、不变文化或序数不正确比较。
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)()
一个完整的扩展方法,适合任何需要快速复制+粘贴的人:
public static class StringComparisonExtensions
{
// from
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();
}
}
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");
}