String.Trim*(params ReadOnlySpan<char>)-Überladungen entfernt
Im .NET-Ökosystem ReadOnlySpan<char>
kann Folgendes dargestellt werden:
- Eine bestimmte Abfolge von Zeichen, häufig als Segment einer größeren System.String Instanz.
- Eine Sammlung einzelner Zeichen, häufig als Segment eines
char[]
.
Frühere Versionen von .NET 9 haben Methodengruppen, die bereits über eine params T[]
Überladung verfügen, Überladungen hinzugefügtparams ReadOnlySpan<T>
. Während diese Überladung eine positive Ergänzung für einige Methodengruppen war, kann die duale Natur ReadOnlySpan<char>
verwirrung für eine Methodengruppe verursachen, die ein und ein char[]
String (in derselben Position) akzeptiert und anders behandelt wird. Betrachtet als Beispiel public static string [String::]Split(string separator, StringSplitOptions options)
die Abfolge von Zeichen als ein Trennzeichen. Beispiel: "[]ne]-[Tw[]".Split("]-[", StringSplitOptions.None)
Teilt sich in new string[] { "[]ne", "Tw[]" };
. Betrachtet dagegen public static [String::]Split(char[] separator, StringSplitOptions options)
jedes Zeichen separator
als separates Trennzeichen, sodass die arrayäquivalente new string[] { "", "", "ne", "", "", "Tw", "", "" }
Teilung ergibt . Daher muss jede neue Überladung, die eine ReadOnlySpan<char>
akzeptiert, entscheiden, ob es sich um eine Zeichenfolge oder ein Array handelt. Im Allgemeinen entspricht .NET dem Array-ähnlichen Verhalten.
Berücksichtigen Sie die folgenden neuen String Überladungen, die ein ReadOnlySpan<char>
Argument wie in dotnet/runtime#77873 vorgeschlagen akzeptieren:
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);
Berücksichtigen Sie außerdem die folgende häufig definierte Erweiterungsmethode:
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;
}
}
Bei vorhandenen .NET-Laufzeiten entfernt diese Erweiterungsmethode die angegebene Sequenz vom Ende der Zeichenfolge. Aufgrund der Regeln für die Überladungsauflösung von C# "12345!!!!".TrimEnd("!!!")
wird jedoch die neue TrimEnd
Überladung gegenüber der vorhandenen Erweiterungsmethode bevorzugt und das Ergebnis von "12345!"
(nur ein vollständiger Satz von drei Ausrufezeichen entfernt) in "12345"
(alle Ausrufezeichen werden vom Ende entfernt).
Um diesen Umbruch zu beheben, gab es zwei mögliche Pfade: Führen Sie eine Instanzmethode public string TrimEnd(string trimString)
ein, die ein noch besseres Ziel ist, oder entfernen Sie die neue Methode. Die erste Option birgt zusätzliche Risiken, da sie entscheiden muss, ob sie eine Instanz der Zielzeichenfolge oder alle davon zurückgibt. Und es gibt zweifellos Aufrufer mit vorhandenem Code, der jeden Ansatz verwendet. Daher war die zweite Option die am besten geeignete Option für diese Phase des Veröffentlichungszyklus.
Anrufer String.Trim , die einzelne Zeichen übergeben, z. B. mit dem params
Feature, str.Trim(';', ',', '.')
werden keine Unterbrechungen angezeigt. Ihr Code wird automatisch von aufrufen string.Trim(params char[])
zu string.Trim(params ReadOnlySpan<char>)
. Wenn Sie mit der GA-Version von .NET 9 neu erstellen, wechselt der Compiler automatisch zurück zur char[]
Überladung.
Anrufer, die explizit einen ReadOnlySpan<char>
(oder einen Typ, ReadOnlySpan<char>
der nicht auch konvertierbar char[]
ist) übergeben, müssen ihren Code ändern, um nach dieser Änderung erfolgreich aufzurufenTrim
.String.Trim
Im Gegensatz dazu String.SplitString.Trimverfügt diese Methode bereits über eine über eine Erweiterungsmethode bevorzugte Überladung, die einen einzelnen Zeichenfolgenparameter und die neu hinzugefügte ReadOnlySpan<char>
Überladung akzeptiert. Aus diesem Grund wurde die neue Überladung String.Split beibehalten.
Hinweis
Sie sollten alle Assemblys neu erstellen, die für .NET 9 Preview 6, .NET 9 Preview 7, .NET 9 RC1 oder .NET 9 RC2 erstellt wurden, um sicherzustellen, dass alle Aufrufe der entfernten Methode entfernt werden. Andernfalls kann dies zur Laufzeit führen MissingMethodException .
Eingeführt in Version
.NET 9 GA
Vorheriges Verhalten
Der folgende Code, der in .NET 9 Preview 6, .NET 9 Preview 7, .NET 9 RC1 und .NET 9 RC2 kompiliert wurde:
private static readonly char[] s_allowedWhitespace = { ' ', '\t', '\u00A0', '\u2000' };
// Only remove the ASCII whitespace.
str = str.Trim(s_allowedWhitespace.AsSpan(0, 2));
Vor .NET 9 Preview 6 wurde "prefixinfix"
der folgende Code zurückgegeben. Für .NET 9 Preview 6 bis .NET 9 RC2 wurde stattdessen Folgendes zurückgegeben "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");
Neues Verhalten
Der folgende Code, der explizit ein Datensegment eines Arrays verwendet, wird nicht mehr kompiliert, da es keine geeignete Überladung für den Aufruf gibt:
private static readonly char[] s_allowedWhitespace = { ' ', '\t', '\u00A0', '\u2000' };
// Only remove the ASCII whitespace.
str = str.Trim(s_allowedWhitespace.AsSpan(0, 2));
Code, der eine Erweiterungsmethode string TrimEnd(this string target, this string suffix)
enthält, hat jetzt das gleiche Verhalten wie in .NET 8 und früheren Versionen. Das heißt, es ergibt "prefixinfix"
sich .
Typ des Breaking Changes
Diese Änderung kann sich auf die binäre Kompatibilität und Quellkompatibilität auswirken.
Grund für die Änderung
Viele Projekte verfügen über Erweiterungsmethoden, die verhaltensbedingte Änderungen nach der Neukompilierung erleben. Die negativen Auswirkungen dieser neuen Instanzmethoden wurden als positiver Nutzen angesehen.
Empfohlene Maßnahme
Kompilieren Sie alle Projekte, die für .NET 9 Preview 6, .NET 9 Preview 7, .NET 9 RC1 oder .NET 9 RC2 erstellt wurden. Wenn das Projekt ohne Fehler kompiliert wird, ist keine weitere Arbeit erforderlich. Wenn das Projekt nicht mehr kompiliert wird, passen Sie den Code an. Ein mögliches Ersatzbeispiel wird hier gezeigt:
-private static ReadOnlySpan<char> s_trimChars = [ ';', ',', '.' ];
+private static readonly char[] s_trimChars = [ ';', ',', '.' ];
...
return input.Trim(s_trimChars);
Betroffene APIs
System.String.Trim(System.ReadOnlySpan{System.Char})
System.String.TrimEnd(System.ReadOnlySpan{System.Char})
System.String.TrimStart(System.ReadOnlySpan{System.Char})