use*_*840 4 .net c# stringcomparer
我一直在使用StringComparer.CurrentCultureIgnoreCase不区分大小写的比较和散列。但是在检查参考源之后,我发现它每次调用都会创建一个新实例(那么它不应该是一个静态函数吗?只是为了形式)。无论如何,我的问题是,当您需要进行多次比较(例如IEquality<T>实现)时,这样做是否有效:
// 2 instances per call
return StringComparer.CurrentCultureIgnoreCase.Equals(this.a, other.a)
&& StringComparer.CurrentCultureIgnoreCase.Equals(this.b, other.b) .. etc ..
Run Code Online (Sandbox Code Playgroud)
或者可能:
public bool Equals(MyObj other)
{
// 1 instance per call
var equ = StringComparer.CurrentCultureIgnoreCase;
return equ.Equals(this.a, other.a)
&& equ.Equals(this.b, other.b) .. etc ..
}
Run Code Online (Sandbox Code Playgroud)
或者甚至缓存/池比较器,这样它们就不会在每次Equals()调用时创建?
// 1 instance per thread
[ThreadStatic]
private static StringComparer equ;
public bool Equals(MyObj other)
{
if (equ == null) equ = StringComparer.CurrentCultureIgnoreCase;
return equ.Equals(this.a, other.a)
&& equ.Equals(this.b, other.b) .. etc ..
}
Run Code Online (Sandbox Code Playgroud)
对最佳实践有何感受?
(感谢 michael-liu 指出 OrdinalIgnoreCase 不是一个新实例,我已切换到 CurrentCultureIgnoreCase)
根据参考资料,OrdinalIgnoreCase每次返回相同的静态实例:
public abstract class StringComparer : ...
{
...
private static readonly StringComparer _ordinalIgnoreCase = new OrdinalComparer(true);
...
public static StringComparer OrdinalIgnoreCase {
get {
Contract.Ensures(Contract.Result<StringComparer>() != null);
return _ordinalIgnoreCase;
}
}
Run Code Online (Sandbox Code Playgroud)
由于在实际的 .NET 可再发行组件中省略了 Contract.Ensures 调用,因此几乎肯定会通过抖动内联剩余的字段访问。
(这同样适用于 InvariantCulture、InvariantCultureIgnoreCase 和 Ordinal。)
另一方面,CurrentCulture 和 CurrentCultureIgnoreCase确实会在您每次访问它们时返回新实例,因为当前区域性可能会在访问之间发生变化。在这种情况下你应该缓存比较器吗?就我个人而言,我不会让我的代码变得更复杂,除非分析表明存在问题。
不过,在这种特殊情况下,我通常会像这样比较字符串是否相等:
return String.Equals(this.a, other.a, StringComparison.OrdinalIgnoreCase);
Run Code Online (Sandbox Code Playgroud)
现在,即使您使用 CurrentCulture 或 CurrentCultureIgnoreCase,您也完全不必担心 StringComparer 分配,并且代码仍然易于阅读。
| 归档时间: |
|
| 查看次数: |
1426 次 |
| 最近记录: |