2010-10-19 7 views
10

Come dice il titolo: Perché lo standard string.Join deve prendere un array anziché un oggetto IEnumerable? Ciò mi infastidisce, dal momento che devo aggiungere un .ToArray() quando ho bisogno di creare una stringa unita dal risultato di un'espressione LINQ.Qual è la ragione per string.Join deve prendere una matrice invece di un oggetto IEnumerable?

La mia esperienza mi dice che mi manca qualcosa di ovvio qui.

+2

Sarete felici di sapere che accetta "IEnumerable " in.NET 4 –

+0

La mia ipotesi sarebbe che è stato aggiunto prima dell'esistenza di IEnumerable. – asawyer

+0

string.Join era qui molto prima di Linq. Come ti infastidisce? Sono solo pochi altri personaggi da scrivere. –

risposta

9

aggiornamento a .NET 4.0 e utilizzare overload che accetta uno IEnumerable<string>. Altrimenti, accetta solo che si trattava di un problema di lunga durata che non è stato risolto fino alla versione 4.0 di .NET. Puoi risolvere il problema creando anche il tuo metodo di estensione!

public static class StringEnumerableExtensions { 
    public static string Join(this IEnumerable<string> strings, string separator) { 
     return String.Join(separator, strings.ToArray()); 
    } 
} 

Usage:

IEnumerable<string> strings; 
Console.WriteLine(strings.Join(", ")); 
+0

Jason, grazie mille, la programmazione è diventata così gioiosa! ':)' – sbi

+0

BTW, in realtà ho scritto un 'Join (questo IEnumerable stringhe, separatore di stringhe)' in aggiunta. Mi sono innamorato così tanto che ho passato a 100kLoC e adattato tutti gli usi di 'string.Join()'. – sbi

3

Non serve più. .NET 4 ha aggiunto some overloads per semplificare l'utilizzo. In particolare, non solo non è necessario passare in un array - non è necessario che sia una sequenza di stringhe. String.Join(String, IEnumerable<T>) chiamerà ToString su ogni elemento nella sequenza.

Se non si utilizza .NET 4 ma si eseguono molte operazioni di unione di stringhe, è possibile scrivere sempre i propri metodi, naturalmente.

+0

Mi stai dicendo che non c'è motivo. NET <4 fa questo ?? – sbi

+0

@sbi: sì. È solo qualcosa che presumibilmente la MS non aveva realizzato sarebbe stato utile agli sviluppatori. Non ha bisogno di nuove funzionalità da .NET 4, per quanto ne so. –

+0

E qui mi aspettavo un trattamento lungo ed educativo sui motivi per cui questo deve essere un array ... – sbi

8

Overloads of Join that take an IEnumerable<T> argument sono stati introdotti in .NET 4 - se non si utilizza .NET 4, allora ho paura che si è bloccato con il passaggio di un array o scrivere la propria implementazione.

Immagino che il motivo sia semplicemente che non è stato ritenuto abbastanza importante quando il framework è stato progettato per la prima volta. IEnumerable<T> è diventato molto più importante con l'introduzione di LINQ.

(Naturalmente, non c'erano tipi generici in .NET durante la progettazione, ma non c'è alcun motivo per cui non avrebbero potuto farlo con semplice IEnumerable non generico se avessero pensato che valesse la pena.)

e non c'è motivo per cui non si può rotolare la propria versione di Join che accetta un IEnumerable<T> se si sente che avete bisogno e siete in grado di eseguire l'aggiornamento a .NET 4.

+0

... a meno che uno non scriva * array-to-'Numerable '*, direi? Questo è ciò che noi gente di Java siamo abituati a fare, comunque. – Esko

0

Direi che String.Join richiede la capacità di scorrere la matrice due volte (una volta per misurare la lunghezza, e una volta a fare la copia). Alcune classi che implementano iEnumerable possono essere unite con successo in un array di stringhe eseguendo un passaggio per contare la lunghezza, chiamando Reset sull'enumeratore e usando un secondo passaggio per copiare i dati, ma poiché iEnumerable non supporta né una proprietà Capabilities, né una famiglia di classi derivate come iMultiPassEnumerable, l'unico modo in cui String.Join può accettare in modo sicuro un IEnumerable potrebbe essere (1) enumerare un qualche tipo di elenco ed eseguire il join su quello, (2) indovinare la dimensione della stringa di destinazione e riallocare come necessario, o (3) combinare gli approcci, raggruppando stringhe corte in gruppi di fino ad es 8K, e quindi combinando tutti i cluster in un risultato finale (che sarebbe una miscela di cluster pre-concatenati e stringhe lunghe dalla matrice originale).

Mentre concederei sicuramente che sarebbe comodo per String.Join includere un overhead che converte un iEnumerable in un elenco, non vedo che fornirebbe più efficienza rispetto a fare tale conversione manualmente (a differenza del versione di array di String.Join, che è più efficiente di unire manualmente le stringhe singolarmente).

Problemi correlati