共用方式為


String.Trim*(params ReadOnlySpan<char>) 多載已移除

在 .NET 生態系統中, ReadOnlySpan<char> 可以代表:

  • 特定字元序列,通常是較大 System.String 實例的配量。
  • 單一字元的集合,通常是 的配 char[]量。

舊版 .NET 9 已將多載新增 params ReadOnlySpan<T> 至已經有 params T[] 多載的方法群組。 雖然這個多載是某些方法群組的正加法,但的 ReadOnlySpan<char> 雙重本質可能會對接受 char[]String (處於相同位置) 的方法群組造成混淆,而且它們會以不同的方式處理。 例如, public static string [String::]Split(string separator, StringSplitOptions options) 將字元序列視為一個分隔符。 例如, "[]ne]-[Tw[]".Split("]-[", StringSplitOptions.None) 分割成 new string[] { "[]ne", "Tw[]" };。 另一方面, public static [String::]Split(char[] separator, StringSplitOptions options) 會將 中的每個 separator 字元視為相異分隔符,因此陣列對等分割會產生 new string[] { "", "", "ne", "", "", "Tw", "", "" }。 因此,任何接受 ReadOnlySpan<char> 的新多載,必須判斷它是否為類似字串或類似陣列的多載。 一般而言,.NET 符合類似數位的行為。

請考慮下列接受 dotnet/runtime#77873 中所建議自變數的新String多載ReadOnlySpan<char>

public string[] Split(params ReadOnlySpan<char> separator);
public string Trim(params ReadOnlySpan<char> trimChars);
public string TrimStart(params ReadOnlySpan<char> trimChars);
public string TrimEnd(params ReadOnlySpan<char> trimChars);

此外,請考慮下列常用的擴充方法:

public static class SomeExtensions {
    public static string TrimEnd(this string target, string trimString) {
        if (target.EndsWith(trimString) {
            return target.Substring(0, target.Length - trimString.Length);
        }

        return target;
    }
}

對於現有的 .NET 運行時間,這個擴充方法會從字串結尾移除指定的序列。 不過,由於 C# 的多載解析規則, "12345!!!!".TrimEnd("!!!") 會偏好使用新的 TrimEnd 多載而不是現有的擴充方法,並將結果從 "12345!" (只移除一組完整的三個驚嘆號) 變更為 "12345" (從結尾移除所有驚歎號)。

若要解決此中斷,有兩個可能的路徑:引進實例方法 public string TrimEnd(string trimString) ,這是更好的目標,或移除新的方法。 第一個選項會帶來額外的風險,因為它需要決定是否傳回目標字串的一個實例或全部實例。 而且毫無疑問,有使用每個方法的現有程序代碼呼叫端。 因此,第二個選項是發行週期這個階段最適當的選擇。

使用params功能傳入個別字元的呼叫端String.Trim,例如 str.Trim(';', ',', '.'),不會看到中斷。 您的程式代碼會自動從呼叫 string.Trim(params char[]) 切換到 string.Trim(params ReadOnlySpan<char>)。 當您針對 .NET 9 的 GA 版本重建時,編譯程式會自動切換回 char[] 多載。

明確傳入的呼叫端String.Trim(或可轉換成ReadOnlySpan<char>且不可轉換成char[]的類型)必須變更其程序代碼,才能在此變更之後成功呼叫TrimReadOnlySpan<char>

至於 String.Split,不同於 String.Trim,這個方法已經有一個多載,兩者都優先於接受單一字元串參數和新加入ReadOnlySpan<char>的多載方法。 基於這個理由,會保留 的新 多載 String.Split

注意

您應該重建針對 .NET 9 Preview 6、.NET 9 Preview 7、.NET 9 RC1 或 .NET 9 RC2 建置的任何元件,以確保移除任何對已移除方法的呼叫。 若無法這麼做,可能會導致 MissingMethodException 在執行時間發生 。

導入的版本

.NET 9 GA

先前的行為

下列程序代碼在 .NET 9 Preview 6、.NET 9 Preview 7、.NET 9 RC1 和 .NET 9 RC2 中編譯:

private static readonly char[] s_allowedWhitespace = { ' ', '\t', '\u00A0', '\u2000' };

// Only remove the ASCII whitespace.
str = str.Trim(s_allowedWhitespace.AsSpan(0, 2));

在 .NET 9 Preview 6 之前,下列程式代碼會產生 "prefixinfix"。 針對 .NET 9 Preview 6 到 .NET 9 RC2,它會改為產生 "prefixin"

internal static string TrimEnd(this string target, string suffix)
{
    if (target.EndsWith(suffix))
    {
        return target.Substring(0, target.Length - suffix.Length);
    }

    return target;
}

...
return "prefixinfixsuffix".TrimEnd("suffix");

新的行為

下列明確使用陣列配量的程式代碼不再編譯,因為沒有適當的多載可供它呼叫:

private static readonly char[] s_allowedWhitespace = { ' ', '\t', '\u00A0', '\u2000' };

// Only remove the ASCII whitespace.
str = str.Trim(s_allowedWhitespace.AsSpan(0, 2));

具有擴充方法 string TrimEnd(this string target, this string suffix) 的程式代碼現在具有與 .NET 8 和舊版相同的行為。 也就是說,它會產生 "prefixinfix"

中斷性變更的類型

此變更可能會影響二進位相容性來源相容性

變更原因

許多專案都有擴充方法,其會在重新編譯之後體驗行為變更。 這些新實例方法的負面影響被認為超過其正面好處。

重新編譯針對 .NET 9 Preview 6、.NET 9 Preview 7、.NET 9 RC1 或 .NET 9 RC2 建置的任何專案。 如果項目編譯時沒有錯誤,則不需要進一步的工作。 如果專案不再編譯,請調整您的程序代碼。 以下顯示可能的替代範例:

-private static ReadOnlySpan<char> s_trimChars = [ ';', ',', '.' ];
+private static readonly char[] s_trimChars = [ ';', ',', '.' ];

...

return input.Trim(s_trimChars);

受影響的 API

  • System.String.Trim(System.ReadOnlySpan{System.Char})
  • System.String.TrimEnd(System.ReadOnlySpan{System.Char})
  • System.String.TrimStart(System.ReadOnlySpan{System.Char})