在 C# 中比較字串

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

CompareCompareTo 預設採用 依文化特性的 比較,而 Equals== 預設採用 序數 比較。 為了避免意外,請傳遞 StringComparison 一個明確的值,讓你的程式碼說明它想要的行為。

使用模式比對 isswitch 來與常數比較

當與其比較的值是常數時,你可以使用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 字串比較最佳實務

另請參閱