String.Trim*(params ReadOnlySpan<char>) przeciążenia usunięte
W ekosystemie ReadOnlySpan<char>
platformy .NET może reprezentować następujące elementy:
- Określona sekwencja znaków, często jako wycinka większego System.String wystąpienia.
- Kolekcja pojedynczych znaków, często jako wycinka .
char[]
Wcześniejsze wersje platformy .NET 9 dodały params ReadOnlySpan<T>
przeciążenia do grup metod, które już miały params T[]
przeciążenie. Chociaż to przeciążenie było pozytywnym dodatkiem dla niektórych grup metod, podwójny charakter ReadOnlySpan<char>
może spowodować zamieszanie dla grupy metod, która akceptuje char[]
element i String (w tej samej pozycji) i są traktowane inaczej. Na przykład public static string [String::]Split(string separator, StringSplitOptions options)
sekwencja znaków jest uwzględniana jako jeden separator. Na przykład "[]ne]-[Tw[]".Split("]-[", StringSplitOptions.None)
dzieli się na new string[] { "[]ne", "Tw[]" };
. Z drugiej strony każdy public static [String::]Split(char[] separator, StringSplitOptions options)
znak w separator
elemencie jest odrębnym separatorem, więc równoważna tablica new string[] { "", "", "ne", "", "", "Tw", "", "" }
zwraca wartość . W związku z tym każde nowe przeciążenie, które akceptuje ReadOnlySpan<char>
, musi zdecydować, czy jest on podobny do ciągu lub tablicy. Ogólnie rzecz biorąc, platforma .NET jest zgodna z zachowaniem przypominającym tablicę.
Rozważ następujące nowe String przeciążenia, które akceptują ReadOnlySpan<char>
argument proponowany w pliku dotnet/runtime#77873:
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);
Ponadto należy wziąć pod uwagę następującą powszechnie zdefiniowaną metodę rozszerzenia:
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;
}
}
W przypadku istniejących środowisk uruchomieniowych platformy .NET ta metoda rozszerzenia usuwa określoną sekwencję z końca ciągu. Jednak ze względu na reguły rozpoznawania przeciążeń języka C# "12345!!!!".TrimEnd("!!!")
, preferuje nowe TrimEnd
przeciążenie istniejącej metody rozszerzenia i zmienia wynik z "12345!"
(usunięcie tylko pełnego zestawu trzech wykrzykników) na "12345"
(usunięcie wszystkich wykrzykników z końca).
Aby rozwiązać ten problem, istnieją dwie możliwe ścieżki: Wprowadź metodę public string TrimEnd(string trimString)
wystąpienia, która jest jeszcze lepszym celem, lub usuń nową metodę. Pierwsza opcja niesie ze sobą dodatkowe ryzyko, ponieważ musi zdecydować, czy zwraca jedno wystąpienie ciągu docelowego, czy wszystkie z nich. Bez wątpienia istnieją osoby wywołujące z istniejącym kodem, który korzysta z każdego podejścia. W związku z tym druga opcja była najbardziej odpowiednią opcją dla tego etapu cyklu wydawania.
Osoby wywołujące String.Trim , które przekazują poszczególne znaki przy użyciu params
funkcji, na przykład str.Trim(';', ',', '.')
, nie będą widzieć przerwy. Kod zostanie automatycznie przełączony z wywołania string.Trim(params char[])
na string.Trim(params ReadOnlySpan<char>)
. Po odbudowaniu wersji ogólnodostępnej platformy .NET 9 kompilator automatycznie przełączy się z powrotem do char[]
przeciążenia.
Osoby wywołujące String.Trim , które jawnie przekazują element ReadOnlySpan<char>
(lub typ, który jest konwertowany na ReadOnlySpan<char>
wartość , nie jest również konwertowany na char[]
), muszą zmienić kod, aby pomyślnie wywołać Trim
po tej zmianie.
Jeśli chodzi o String.Split, w przeciwieństwie do String.Trimmetody , ta metoda ma już przeciążenie , które jest preferowane dla metody rozszerzenia akceptującej pojedynczy parametr ciągu i nowo dodane ReadOnlySpan<char>
przeciążenie. Z tego powodu nowe przeciążenie String.Split zostało zachowane.
Uwaga
Należy ponownie skompilować zestaw utworzony na platformie .NET 9 (wersja zapoznawcza 6), .NET 9 (wersja zapoznawcza 7), .NET 9 RC1 lub .NET 9 RC2, aby upewnić się, że wszystkie wywołania metody usuniętej zostaną usunięte. Niepowodzenie w tym celu może spowodować powstanie błędu MissingMethodException w czasie wykonywania.
Wprowadzona wersja
Ogólna dostępność platformy .NET 9
Poprzednie zachowanie
Następujący kod skompilowany w programie .NET 9 (wersja zapoznawcza 6), .NET 9 (wersja zapoznawcza 7), .NET 9 RC1 i .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));
Przed programem .NET 9 (wersja zapoznawcza 6) poniższy kod daje wartość "prefixinfix"
. W przypadku platformy .NET 9 (wersja zapoznawcza 6 do .NET 9 RC2) zamiast tego została zwrócona wartość "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");
Nowe zachowanie
Poniższy kod, który jawnie używa wycinka tablicy, nie jest już kompilowany, ponieważ nie ma odpowiedniego przeciążenia do wywołania:
private static readonly char[] s_allowedWhitespace = { ' ', '\t', '\u00A0', '\u2000' };
// Only remove the ASCII whitespace.
str = str.Trim(s_allowedWhitespace.AsSpan(0, 2));
Kod, który zawiera metodę string TrimEnd(this string target, this string suffix)
rozszerzenia, ma teraz takie samo zachowanie jak w programie .NET 8 i poprzednich wersjach. Oznacza to, że daje "prefixinfix"
wartość .
Typ zmiany powodującej niezgodność
Ta zmiana może mieć wpływ na zgodność binarną i zgodność ze źródłem.
Przyczyna wprowadzenia zmiany
Wiele projektów ma metody rozszerzeń, które doświadczają zmian behawioralnych po ponownym skompilowaniu. Negatywny wpływ tych nowych metod wystąpień został uznany za przeważony nad ich pozytywnymi korzyściami.
Zalecana akcja
Ponownie skompiluj wszystkie projekty utworzone na platformie .NET 9 (wersja zapoznawcza 6), .NET 9 (wersja zapoznawcza 7), .NET 9 RC1 lub .NET 9 RC2. Jeśli projekt kompiluje się bez błędów, nie jest wymagana żadna dalsza praca. Jeśli projekt nie jest już kompilowany, dostosuj kod. Poniżej przedstawiono jeden z możliwych przykładów podstawienia:
-private static ReadOnlySpan<char> s_trimChars = [ ';', ',', '.' ];
+private static readonly char[] s_trimChars = [ ';', ',', '.' ];
...
return input.Trim(s_trimChars);
Dotyczy interfejsów API
System.String.Trim(System.ReadOnlySpan{System.Char})
System.String.TrimEnd(System.ReadOnlySpan{System.Char})
System.String.TrimStart(System.ReadOnlySpan{System.Char})