Delen via


String.Trim*(params ReadOnlySpan<char>) overbelasting verwijderd

In het .NET-ecosysteem ReadOnlySpan<char> kunt u het volgende voorstellen:

  • Een specifieke reeks tekens, vaak als een segment van een groter System.String exemplaar.
  • Een verzameling van één tekens, vaak als een segment van een char[].

In eerdere versies van .NET 9 zijn overbelastingen toegevoegd params ReadOnlySpan<T> aan methodegroepen die al een params T[] overbelasting hadden. Hoewel deze overbelasting een positieve toevoeging was voor sommige methodegroepen, kan de dubbele aard van ReadOnlySpan<char> een methodegroep verwarring veroorzaken die een char[] en een String (in dezelfde positie) accepteert en ze anders worden behandeld. Beschouw bijvoorbeeld public static string [String::]Split(string separator, StringSplitOptions options) de reeks tekens als één scheidingsteken. Bijvoorbeeld "[]ne]-[Tw[]".Split("]-[", StringSplitOptions.None) gesplitst in new string[] { "[]ne", "Tw[]" };. Aan de andere kant public static [String::]Split(char[] separator, StringSplitOptions options) wordt elk teken als een uniek scheidingsteken beschouwd separator , dus de splitsopbrengsten new string[] { "", "", "ne", "", "", "Tw", "", "" }van matrixequivalenten. Daarom moet elke nieuwe overbelasting die een ReadOnlySpan<char> accepteert, beslissen of deze tekenreeksachtig of matrixachtig is. Over het algemeen voldoet .NET aan het matrixachtige gedrag.

Houd rekening met de volgende nieuwe String overbelastingen die een ReadOnlySpan<char> argument accepteren zoals voorgesteld in 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);

Overweeg bovendien de volgende algemeen gedefinieerde extensiemethode:

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;
    }
}

Voor bestaande .NET-runtimes verwijdert deze extensiemethode de opgegeven reeks van het einde van de tekenreeks. Vanwege de regels voor overbelastingsresolutie van C# geeft u "12345!!!!".TrimEnd("!!!") echter de voorkeur aan de nieuwe TrimEnd overbelasting boven de bestaande uitbreidingsmethode en wijzigt u het resultaat van "12345!" (alleen een volledige set van drie uitroeptekens verwijderen) in "12345" (alle uitroeptekens van het einde verwijderen).

Er zijn twee mogelijke paden om dit einde op te lossen: introduceer een instantiemethode public string TrimEnd(string trimString) die een nog beter doel is of verwijder de nieuwe methode. De eerste optie brengt extra risico met zich mee, omdat er moet worden bepaald of er één exemplaar van de doeltekenreeks of allemaal wordt geretourneerd. En er zijn ongetwijfeld bellers met bestaande code die elke benadering gebruikt. Daarom was de tweede optie de meest geschikte keuze voor deze fase van de releasecyclus.

Bellers van wie afzonderlijke tekens doorgeeft met behulp van String.Trim de params functie, str.Trim(';', ',', '.')zien bijvoorbeeld geen onderbreking. Uw code is automatisch overgeschakeld van aanroepen string.Trim(params char[]) naar string.Trim(params ReadOnlySpan<char>). Wanneer u opnieuw bouwt op basis van de GA-versie van .NET 9, wordt de compiler automatisch teruggezet naar de char[] overbelasting.

Bellers van String.Trim wie expliciet een ReadOnlySpan<char> (of een type dat converteerbaar is naar ReadOnlySpan<char> dat niet ook converteerbaar char[]is) moeten hun code wijzigen om na deze wijziging met succes aan te roepen Trim .

Net als bij String.Split, in tegenstelling tot bij String.Trim, heeft deze methode al een overbelasting die beide voorkeur heeft boven een extensiemethode die een enkele tekenreeksparameter accepteert en de zojuist toegevoegde ReadOnlySpan<char> overbelasting. Daarom bleef de nieuwe overbelasting String.Split behouden.

Notitie

U moet elke assembly die is gebouwd op basis van .NET 9 Preview 6, .NET 9 Preview 7, .NET 9 RC1 of .NET 9 RC2 opnieuw bouwen om ervoor te zorgen dat alle aanroepen naar de verwijderde methode worden verwijderd. Als u dit niet doet, kan dit leiden tot een MissingMethodException runtime.

Versie geïntroduceerd

.NET 9 GA

Vorig gedrag

De volgende code gecompileerd in .NET 9 Preview 6, .NET 9 Preview 7, .NET 9 RC1 en .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));

Vóór .NET 9 Preview 6 heeft de volgende code opgeleverd "prefixinfix". Voor .NET 9 Preview 6 tot en met .NET 9 RC2 heeft het in plaats daarvan het volgende "prefixin"opgeleverd:

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");

Nieuw gedrag

De volgende code die expliciet gebruikmaakt van een segment van een matrix wordt niet meer gecompileerd, omdat er geen geschikte overbelasting is om aan te roepen:

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

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

Code die een extensiemethode string TrimEnd(this string target, this string suffix) bevat, heeft nu hetzelfde gedrag als in .NET 8 en eerdere versies. Dat wil gezegd, het levert op "prefixinfix".

Type wijziging die fouten veroorzaken

Deze wijziging kan van invloed zijn op binaire compatibiliteit en broncompatibiliteit.

Reden voor wijziging

Veel projecten hebben uitbreidingsmethoden die gedragswijzigingen ervaren na het opnieuw compileren. De negatieve gevolgen van deze nieuwe instantiemethoden werden geacht op te wegen tegen hun positieve voordeel.

Compileer alle projecten die zijn gebouwd op basis van .NET 9 Preview 6, .NET 9 Preview 7, .NET 9 RC1 of .NET 9 RC2. Als het project zonder fouten compileert, is er geen verdere werkzaamheden vereist. Als het project niet meer wordt gecompileerd, past u de code aan. Hier ziet u een mogelijk vervangingsvoorbeeld:

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

...

return input.Trim(s_trimChars);

Betrokken API's

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