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表達式。 每個分支都會測試一個 常數模式,而捨棄模式(_)則會處理所有不符合比對的值。 下一個範例將方向關鍵字映射到旅行指令:
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 字串比較最佳實務。