Overload String.Trim*(params ReadOnlySpan<char>) rimossi
Nell'ecosistema ReadOnlySpan<char>
.NET può rappresentare:
- Sequenza specifica di caratteri, spesso come sezione di un'istanza più grande System.String .
- Raccolta di singoli caratteri, spesso come sezione di un oggetto
char[]
.
Le versioni precedenti di .NET 9 hanno aggiunto params ReadOnlySpan<T>
overload ai gruppi di metodi che avevano già un params T[]
overload. Anche se questo overload è stato un'aggiunta positiva per alcuni gruppi di metodi, la doppia natura di può causare confusione per un gruppo di ReadOnlySpan<char>
metodi che accetta e char[]
( String nella stessa posizione) e vengono trattati in modo diverso. Ad esempio, public static string [String::]Split(string separator, StringSplitOptions options)
considera la sequenza di caratteri come un separatore. Ad esempio, "[]ne]-[Tw[]".Split("]-[", StringSplitOptions.None)
suddivide in new string[] { "[]ne", "Tw[]" };
. D'altra parte, public static [String::]Split(char[] separator, StringSplitOptions options)
considera ogni carattere in separator
come separatore distinto, quindi la divisione equivalente alla matrice restituisce new string[] { "", "", "ne", "", "", "Tw", "", "" }
. Di conseguenza, qualsiasi nuovo overload che accetta un ReadOnlySpan<char>
oggetto deve decidere se è simile a una stringa o a una matrice. In generale, .NET è conforme al comportamento simile alla matrice.
Considerare i nuovi String overload seguenti che accettano un ReadOnlySpan<char>
argomento come proposto 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);
Si consideri anche il metodo di estensione comunemente definito di seguito:
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;
}
}
Per i runtime .NET esistenti, questo metodo di estensione rimuove la sequenza specificata dalla fine della stringa. Tuttavia, a causa delle regole di risoluzione dell'overload di C#, "12345!!!!".TrimEnd("!!!")
preferirà il nuovo TrimEnd
overload rispetto al metodo di estensione esistente e cambierà il risultato da "12345!"
(rimuovendo solo un set completo di tre punti esclamativi) a "12345"
(rimuovendo tutti i segni esclamativi dalla fine).
Per risolvere l'interruzione, esistono due possibili percorsi: introdurre un metodo public string TrimEnd(string trimString)
di istanza che rappresenta una destinazione ancora migliore o rimuovere il nuovo metodo. La prima opzione comporta rischi aggiuntivi, perché deve decidere se restituisce un'istanza della stringa di destinazione o tutte. E ci sono senza dubbio chiamanti con codice esistente che usa ogni approccio. Pertanto, la seconda opzione è stata la scelta più appropriata per questa fase del ciclo di rilascio.
I chiamanti di String.Trim che passano singoli caratteri usando la params
funzionalità, ad esempio , str.Trim(';', ',', '.')
non vedranno un'interruzione. Il codice passerà automaticamente dalla chiamata string.Trim(params char[])
a string.Trim(params ReadOnlySpan<char>)
. Quando si esegue la ricompilazione rispetto alla versione ga di .NET 9, il compilatore tornerà automaticamente all'overload char[]
.
I chiamanti di String.Trim che passano in modo esplicito un ReadOnlySpan<char>
oggetto (o un tipo convertibile in ReadOnlySpan<char>
che non è convertibile anche in char[]
) devono modificare il codice in modo da chiamare Trim
correttamente dopo questa modifica.
Per quanto riguarda String.Split, a differenza di String.Trim, questo metodo ha già un overload che è preferibile a un metodo di estensione che accetta un singolo parametro stringa e l'overload appena aggiunto ReadOnlySpan<char>
. Per questo motivo, il nuovo overload di String.Split è stato mantenuto.
Nota
È necessario ricompilare qualsiasi assembly compilato in .NET 9 Preview 6, .NET 9 Preview 7, .NET 9 RC1 o .NET 9 RC2 per assicurarsi che tutte le chiamate al metodo rimosso vengano rimosse. In caso contrario, potrebbe verificarsi un MissingMethodException errore in fase di esecuzione.
Versione introdotta
.NET 9 GA
Comportamento precedente
Il codice seguente compilato in .NET 9 Preview 6, .NET 9 Preview 7, .NET 9 RC1 e .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));
Prima di .NET 9 Preview 6, il codice seguente ha restituito "prefixinfix"
. Per .NET 9 Preview 6 e .NET 9 RC2, invece ha restituito "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");
Nuovo comportamento
Il codice seguente che usa in modo esplicito una sezione di una matrice non viene più compilato, perché non esiste alcun overload appropriato per la chiamata:
private static readonly char[] s_allowedWhitespace = { ' ', '\t', '\u00A0', '\u2000' };
// Only remove the ASCII whitespace.
str = str.Trim(s_allowedWhitespace.AsSpan(0, 2));
Il codice che include un metodo string TrimEnd(this string target, this string suffix)
di estensione ha ora lo stesso comportamento in .NET 8 e versioni precedenti. Ovvero, restituisce "prefixinfix"
.
Tipo di modifica che causa un'interruzione
Questa modifica può influire sulla compatibilità binaria e sulla compatibilità dell'origine.
Motivo della modifica
Molti progetti hanno metodi di estensione che sperimentano modifiche comportamentali dopo la ricompilazione. L'impatto negativo di questi nuovi metodi di istanza è stato considerato superiore al vantaggio positivo.
Azione consigliata
Ricompilare tutti i progetti compilati in .NET 9 Preview 6, .NET 9 Preview 7, .NET 9 RC1 o .NET 9 RC2. Se il progetto viene compilato senza errori, non è necessario eseguire ulteriori operazioni. Se il progetto non viene più compilato, modificare il codice. Di seguito è riportato un possibile esempio di sostituzione:
-private static ReadOnlySpan<char> s_trimChars = [ ';', ',', '.' ];
+private static readonly char[] s_trimChars = [ ';', ',', '.' ];
...
return input.Trim(s_trimChars);
API interessate
System.String.Trim(System.ReadOnlySpan{System.Char})
System.String.TrimEnd(System.ReadOnlySpan{System.Char})
System.String.TrimStart(System.ReadOnlySpan{System.Char})