Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В экосистеме ReadOnlySpan<char>
.NET может представлять следующее:
- Определенная последовательность символов часто в виде среза большего System.String экземпляра.
- Коллекция отдельных символов часто в виде среза
char[]
.
Более ранние выпуски .NET 9 добавили params ReadOnlySpan<T>
перегрузки в группы методов, которые уже имели перегрузку params T[]
. Хотя эта перегрузка была положительным дополнением для некоторых групп методов, двойной характер ReadOnlySpan<char>
может вызвать путаницу для группы методов, которая принимает char[]
и a 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 соответствует поведению, подобному массиву.
Рассмотрим следующие новые String перегрузки, которые принимают ReadOnlySpan<char>
аргумент, как предлагается в 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);
Кроме того, рассмотрим следующий распространенный метод расширения:
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)
экземпляра, который является еще более лучшим целевым объектом, или удалите новый метод. Первый вариант несет дополнительный риск, так как он должен решить, возвращает ли он один экземпляр целевой строки или все из них. И есть, несомненно, вызывающие существующий код, который использует каждый подход. Поэтому второй вариант был наиболее подходящим вариантом для этого этапа цикла выпуска.
Вызывающие String.Trim лица, которые проходят отдельные символы с помощью params
функции, например, str.Trim(';', ',', '.')
не увидят перерыв. Ваш код автоматически переключится с вызова string.Trim(params char[])
string.Trim(params ReadOnlySpan<char>)
. При перестроении в общедоступной версии .NET 9 компилятор автоматически переключится на перегрузку char[]
.
Вызывающие лица String.Trim , которые явно передают код ( ReadOnlySpan<char>
или тип, который преобразуется ReadOnlySpan<char>
в это не также преобразуется char[]
) должны изменить код, чтобы успешно вызвать Trim
после этого изменения.
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
Прежнее поведение
Следующий код, скомпилированный в .NET 9 (предварительная версия 6), .NET 9 (предварительная версия 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 (предварительная версия 6) приведенный ниже код был получен "prefixinfix"
. Для .NET 9( предварительная версия 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})