Tip
本文是已了解至少一种编程语言并正在学习 C# 的开发人员的 “基础知识 ”部分的一部分。 如果你不熟悉编程,请先 学习入门 教程。
来自另一种语言? 在 C# 中,对字符串使用 == 时比较的是 值,而不是引用,这很像 Java 的 equals 或 JavaScript 的 ===。 关键区别在于,C# 允许你通过 StringComparison 值选择使用 序数(二进制)比较还是 区域性相关比较。
比较字符串以回答以下两个问题之一: 这两个字符串是否相等? 或 这些字符串排序的顺序是什么? C# 允许在回答任一问题时控制两个独立因素:
-
区分大小写 — 是否将
"Hello"和"hello"视为相同。 - 比较种类 — 序值(比较每个字符的二进制值)或 区域性(应用特定区域的语言规则)。
枚举 StringComparison 将这些因素合并到传递给比较方法的单个值中。
相等性比较
默认情况下,String.Equals 方法和 == 运算符都执行区分大小写且按序号进行的比较。 序号比较检查每个字符的二进制值,因此它很快,并在每台计算机上提供相同的结果。 你可以通过调用接受 StringComparison 值的重载版本来明确表明你的意图:
string root = @"C:\users";
string root2 = @"C:\Users";
// Equals and == both perform a case-sensitive, ordinal comparison.
Console.WriteLine(root.Equals(root2));
// => False
Console.WriteLine(root == root2);
// => False
// Pass a StringComparison value to state the intent explicitly.
Console.WriteLine(root.Equals(root2, StringComparison.Ordinal));
// => False
若要在保留序号语义时忽略大小写,请传递 StringComparison.OrdinalIgnoreCase:
string root = @"C:\users";
string root2 = @"C:\Users";
// OrdinalIgnoreCase compares the binary values but ignores case.
bool equalIgnoringCase = string.Equals(root, root2, StringComparison.OrdinalIgnoreCase);
Console.WriteLine(equalIgnoringCase);
// => True
按排序顺序比较
若要确定排序顺序而不是相等,请使用 String.Compare。 它返回负数、零或正数,以指示第一个字符串是在之前、与第二个字符串位于同一位置还是之后进行排序:
string first = "Avocado";
string second = "Banana";
// Compare returns a negative number, zero, or a positive number
// to indicate sort order. Specify the comparison type explicitly.
int order = string.Compare(first, second, StringComparison.Ordinal);
Console.WriteLine(order < 0
? $"'{first}' sorts before '{second}'."
: $"'{first}' sorts at or after '{second}'.");
// => 'Avocado' sorts before 'Banana'.
Important
Compare 和 CompareTo 默认使用 区域性相关 比较,而 Equals 和 == 默认使用 序号 比较。 为了避免意外,请传递显式 StringComparison 值,以便代码指出它想要的行为。
使用模式匹配 is 或 switch 与常量进行比较
如果与常量进行比较的值是常量,则可以将 is 运算符 与 常量模式 一起使用,作为可读的替代方法 ==:
string status = "Ready";
// When the right operand is a constant, the is operator and a
// constant pattern read as an alternative to ==.
if (status is "Ready")
{
Console.WriteLine("The system is ready.");
}
// => The system is ready.
若要将字符串与多个常量进行比较,请使用 switch 表达式。 每个 arm 都会测试 一个常量模式,丢弃模式 (_) 处理不匹配的每个值。 下一个示例将方向关键字映射到旅行说明:
foreach (string heading in new[] { "North", "South", "East", "West", "NE" })
{
// A switch expression matches each constant pattern in turn and
// returns the first match. The discard (_) handles every other value.
string instruction = heading switch
{
"North" => "Travel due North for 10 km.",
"South" => "Travel due South for 10 km.",
"East" => "Travel due East for 10 km.",
"West" => "Travel due West for 10 km.",
_ => $"Unknown heading: {heading}.",
};
Console.WriteLine(instruction);
}
// => Travel due North for 10 km.
// => Travel due South for 10 km.
// => Travel due East for 10 km.
// => Travel due West for 10 km.
// => Unknown heading: NE.
测试字符串常量的 switch 表达式会执行与 == 相同的区分大小写的序号比较,因此 "north" 与 "North" 分支不匹配。
选择正确的比较
根据数据选择比较方式,而不是凭习惯:
- 对于标识符、文件路径、协议令牌和其他计算机定义的文本,请使用 Ordinal (或 OrdinalIgnoreCase 忽略大小写)。 序数比较快速且在不同文化之间保持一致。
- 对于供用户阅读和排序的文本(例如姓名或产品标题),请使用 CurrentCulture,以便排序顺序符合用户的预期。
区域性比较会使用因区域性而异的语言规则,因此可能产生令人惊讶的结果。 例如,某些区域性设置会将 "ss" 和 "ß" 视为相等,并且字符串的排序结果在不同计算机之间可能会有所不同。 由于存在这种可变性,因此仅应将区域性相关的比较用于真正的自然语言文本,并且在对同一集合同时进行排序和搜索时,应使用相同的比较方式。
有关区域性敏感的比较(包括全球化相关注意事项和平台差异)的深入介绍,请参阅在 .NET 中比较字符串的最佳做法。