Ragioni dietro l'implementazione non intuitiva di C # String.Split ()

9

In C # se voglio dividere un string di un altro string Devo fare qualcosa del genere:

testString.Split(new string[] { "anotherString" }, StringSplitOptions.None);

Dalla String.Split documentazione MSDN in sovraccarico possiamo vedere l'implementazione e perché tale la chiamata deve essere fatta.

Provenendo da Python , è difficile per me capire correttamente perché è necessaria una tale chiamata. Voglio dire che potrei usare Regex.Split per ottenere una sintassi simile rispetto all'implementazione di Python ma dovrei farlo a costo di meno prestazioni (tempo di setup) per qualsiasi cosa semplice .

Quindi in fondo, la mia domanda è: perché diavolo non possiamo semplicemente fare:

testString.Split("anotherString");

Nota che non sto suggerendo alcun prototipo né implementazione. Capisco perché non è possibile implementare la versione precedente considerando l'API corrente. Il mio obiettivo era capire perché una tale API avrebbe potuto essere creata considerando il beneficio che la sintassi sopra riportata comporta. A partire da ora, flessibilità sembra essere l'obiettivo dell'attuale String.Split che ha senso, ma ad essere onesti ho davvero pensato che ci fosse un qualche tipo di guadagno da qualche parte. Credo di essermi sbagliato.

    
posta scharette 08.06.2018 - 16:24
fonte

3 risposte

14

A volte la suddivisione su più di un char / stringa è utile, quindi l'API ti consente di fornire un array, offrendoti la massima flessibilità. Nel caso di char s, ottieni sia la semplicità della sintassi che la flessibilità poiché il parametro è contrassegnato come params , quindi puoi scrivere Split('x') piuttosto che Split(new[]{'x'}) .

Quindi, perché non esiste un'opzione simile per le stringhe, che consente di scrivere Split("x") ?

Questa è forse una sfortunata conseguenza di come viene progettata l'API. Inizialmente consentiva solo la suddivisione in caratteri. La divisione su stringhe è stata aggiunta in 2.0, probabilmente perché è più complessa da implementare. Ma non è stato possibile aggiungere String.Split(string) o String.Split(string[]) overload, poiché ciò renderebbe l'espressione testString.Split(null) ambigua e questo codice non sarebbe più compilato.

testString.Split(null) è in realtà un idioma piuttosto comune poiché divide la stringa in spazi vuoti, quindi una tale rottura sarebbe troppo diffusa per essere accettabile.

L'uso di un parametro null come parametro per un comportamento speciale è generalmente considerato un cattivo design in questi giorni, quindi penso che sia giusto dire che questa API è solo difettosa.

Non c'è neanche Split(string[], Int32) , probabilmente per un motivo simile - sarebbe ambiguo con Split(char[], Int32) se il primo parametro è null . Ci sono sovraccarichi simili con i parametri StringSplitOptions , ma questi sono stati tutti aggiunti alla stessa ora in 2.0, quindi non è stata introdotta alcuna ambiguità nel codice esistente.

Nota

Per essere chiari, questa è solo la mia ipotesi, non conosco il pensiero reale dei progettisti del framework .net.

    
risposta data 08.06.2018 - 20:34
fonte
2

Non essendo l'autore dei metodi, non so perché è stata scelta questa serie di sovraccarichi. Tuttavia, ci sono due cose da notare qui:

  1. Se stai dividendo su un singolo personaggio, allora la versione public string[] Split(params char[] separator ) può essere usata così:

    var splitValues = testString.Split(',');
    

    come char[] è un parametro params .

  2. Puoi facilmente aggiungere qui il tuo metodo di estensione per ottenere ciò che desideri:

    public static class StringExtensions
    {
        public static string[] Split(this string source, string separator)
            => source.Split(new string[] { separator }, StringSplitOptions.None);
    }
    

    e ora testString.Split("anotherString"); funzionerà per te.

risposta data 08.06.2018 - 17:06
fonte
1

Diverse lingue hanno regole un po 'diverse per conversioni implicite e sovraccarico, e .NET Framework è progettato per essere utilizzabile con qualsiasi di esse. Nel dialetto Option Strict Off di VB.NET, un valore di tipo String può essere passato a una funzione che si aspetta un Char[] con un comportamento equivalente a chiamare ToCharArray() sulla stringa.

Penso che la cosa sensata da fare sarebbe stata avere nomi separati per Split (che accetta un singolo Char o String ) e SplitMulti (che accetterebbe un Char[] o String[] ), ma a volte .NET sembra preferire l'utilizzo dell'overloading da solo per selezionare diversi tipi di operazioni. Sfortunatamente, non conosco alcun modo di utilizzare String.Split per adattarsi a qualsiasi scenario di utilizzo che richiederebbe la distinzione di diversi tipi di delimitatori diversi dalla suddivisione separata su ciascuno.

Un'altra omissione è un'opzione per preservare i delimitatori, includendoli alla fine della stringa precedente o all'inizio della seguente stringa, oppure se gli elementi di matrice dispari sono delimitatori mentre gli elementi pari sono gli elementi tra loro.

    
risposta data 08.06.2018 - 20:38
fonte

Leggi altre domande sui tag