初学者教程:C# 中的字符串比较






4.67/5 (22投票s)
这篇简短的文章向您展示了在 C# 应用程序中比较字符串的正确方法。
引言
这篇短文讨论了在 C# 应用程序中比较 string
的正确方法。我们将尝试了解比较 string
的各种方法,以及哪种方法应该使用,哪种不应该使用。
背景
通常在我们的应用程序中,当我们想比较两个 string
时,我们会使用相等运算符。在大多数情况下,这都能正常工作,但我们仍然应该知道我们还可以通过其他哪些方式进行 string
比较,并可能获得更好的性能和结果。所以,假设我有一个变量 str
,我想检查它的值是否等于“Yes
”。
if(str == "Yes")
{
// equal
}
else
{
// not equal
}
上面提到的运算符将以区分大小写的方式进行比较,并且不会考虑当前区域性。现在,如果需要不区分大小写的比较,我见过大多数开发人员会采用以下几种方法。
要么我们这样做
if (str.ToLower() == "yes")
{
//equal
}
else
{
//not equal
}
或者我们这样做
if (str.ToUpper() == "YES")
{
//equal
}
else
{
//not equal
}
现在这在大多数情况下都能正常工作,而且由于 string
的不可变性,我的原始 string
甚至不会被修改,但这确实涉及额外的函数调用和创建一个额外的临时 string
变量(调用 ToLower()
或 ToUpper()
)。而且,如果这段代码在一个对区域性敏感的应用程序中运行,并且 str
变量可能包含一些非英文字符,那么这种方法将不起作用。
那么,我们如何以一种可以规避所有这些问题的方式进行 string
比较呢?.NET Framework 的 string
类已经考虑了所有这些场景,并提供了一些函数,使我们能够在所有这些场景中执行正确且最优的 string
比较。现在我们来看看这些函数。
注意:我们将讨论相等性比较,但所有这些要点对于其他比较也是有效的,即查找 string
的顺序等。
Using the Code
在深入研究函数之前,首先要理解的是我可能需要的比较类型。我可能需要区分区域性的比较或不区分区域性的比较(序数比较)。其次,我可能想要区分大小写的信息或不区分大小写的比较。
现在让我们看看 .NET 为我们提供了什么。 .NET 提供了 3 种模式
CultureInvariant
CurrentCulture
Ordinal
CultureInvariant
CultureInvariant
模式假设所有比较都将以英语和 en-US 区域性进行。此模式根据特定字母表来解释字符。字母表的排序假设 en-US 为区域性。此模式最终可以被视为使用类似这样的字符串来查找字符串的顺序:"AaBbCc..."
。因此,在此模式下,“CAT
”和“bat
”的排序将是:“bat
”,“CAT
”。
CurrentCulture
第二种模式 CurrentCulture
将按照 Invariant 模式的字母表顺序排列来查找 string
的顺序,只是这个顺序是区域性特定的。
此外,在此模式下,字符会与其在其他区域性中的对应字符进行比较,也就是说,德语的 Ä
将被视为 en-US 的 A
。
Ordinal
第三种模式 Ordinal 简单地根据字符的顺序来比较 string
。换句话说,它只是使用字符的 Unicode 值来查找顺序。它使用以下参考 string
来排序 string
。这不过是按照其 Unicode/ASCII 值排序的所有字母:"ABC...abc..."
。因此,在此模式下,“CAT
”和“bat
”的排序将是:“CAT
”,“bat
”。
现在有了这些信息,让我们看看 .NET 为我们提供了什么。String.Equals
和 compare
函数有一个重载版本,它接受 StringComparison
enum
类型作为参数。此参数将指定我们要用于此比较的模式。
public static bool Equals (string a, string b, StringComparison comparisonType);
此 enum
可能有以下值
CurrentCulture
CurrentCultureIgnoreCase
InvariantCulture
InvariantCultureIgnoreCase
Ordinal
OrdinalIgnoreCase
查看每个 enum
值,对于哪种模式适用于哪种场景,不言而喻。尽管如此,我们还是为此绘制一个小型矩阵。
CaseSensitive | 不区分大小写 | |
区分区域性 | CurrentCulture | CurrentCultureIgnoreCase |
不区分区域性(英语 en-US) | InvariantCulture | InvariantCultureIgnoreCase |
Order | Ordinal | OrdinalIgnoreCase |
现在,我将使用这些模式执行上面看到的相同的比较。
以区分大小写的方式逐个字符比较 string
if (String.Equals(str, "Yes", StringComparison.Ordinal) == true)
{
//equal
}
else
{
//not equal
}
以不区分大小写的方式比较 string
if (String.Equals(str, "Yes", StringComparison.OrdinalIgnoreCase) == true)
{
//equal
}
else
{
//not equal
}
这些代码片段也将为我们提供所需的结果,并且可能比以前更有效率。
注意:==
运算符等同于 <code>StringComparison
.Ordinal。因此,如果我们想使用此模式,我们可以直接使用 ==
运算符。
现在让我们总结一下,看看何时应该使用哪种方法
CurrentCulture
- 区分区域性且区分大小写的比较CurrentCultureIgnoreCase
- 区分区域性但不区分大小写的比较InvariantCulture
- 仅英语且区分大小写的比较InvariantCultureIgnoreCase
- 仅英语且不区分大小写的比较Ordinal
- 基于 ASCII/UNICODE 值且区分大小写的比较OrdinalIgnoreCase
- 基于 ASCII/UNICODE 值且不区分大小写的比较
关于 StringComparer 和 StringComparison 的说明
一个非常有趣的混淆点是,对于所有类似的 string
比较,都有可能使用 StringComparer
类。此类也具有所有这六种进行 string
比较的方式。需要注意的重要一点是,这个 Class
还实现了比较接口,即 IComparer
、IEqualityComparer
、IComparer<String>
。
到目前为止,我们在本文中讨论的 StringComparison
是一个 enum
,您在比较两个 string
时应该使用它。那么,我们何时不应使用上述方法而选择 StringComparer
类呢?
经验法则是,如果只需要 string
比较,那么我们应该使用 String
类的 String.Equals
等方法,这些方法将使用 StringComparison enum
来确定实际比较应该使用哪种模式。您应该仅在有某些方法接受 IComparer
、IEqualityComparer
、IComparer<String>
类型之一作为参数,并且我们需要传递我们的 string
时,才应使用 StringComparer
类。
也许,从内部来看,String
类的函数仍然使用 StringComparer
类进行实际比较,但从开发者的角度来看,遵循上述指南就足够了。
看点
这篇简短的文章是为那些职业生涯刚开始并且正在以各种形式操作 string
来达到期望的比较结果的开发者编写的。我们只讨论了相等性操作,但比较运算符也将遵循相同的规则。
历史
- 2012 年 8 月 24 日:第一个版本