2011-02-03 2 views
32

Ho un oggetto che contiene molti valori, alcuni di essi (non tutti i valori dell'oggetto) devono essere inseriti in una stringa csv. Il mio approccio era questo:Crea stringhe separate da virgola C#?

string csvString = o.number + "," + o.id + "," + o.whatever .... 

In qualche modo penso che ci sia un modo migliore, più elegante?

+0

In generale è considerato meno efficiente concatenare stringhe con il simbolo '+'. Crea più oggetti da raccogliere. –

+0

[Separazione manuale della virgola contro la bella classe CommaDelimitedStringCollection!] (Http://izlooite.blogspot.com/2009/12/manual-comma-separation-versus-cool.html) –

risposta

73

Se si inseriscono tutti i valori in un array, almeno è possibile utilizzare string.Join.

string[] myValues = new string[] { ... }; 
string csvString = string.Join(",", myValues); 

È anche possibile utilizzare il sovraccarico di string.Join che prende params string come secondo parametro in questo modo:

string csvString = string.Join(",", value1, value2, value3, ...); 
+0

+1 per l'utilizzo di un array tra il quale mantiene il codice più leggibile quando ci sono più di "pochi" valori. – Bazzz

+0

@Bazzz - Sì, potrebbe rapidamente diventare disordinato se si immettono 10+ parametri nella chiamata del metodo di join. Penso che il primo approccio sia quello più pulito, ma per alcuni valori, anche il secondo è ok. –

+0

Perché due downvote su questa risposta? Un motivo sarebbe apprezzato in modo che tutti sappiano quali sono i tuoi problemi con questa risposta. –

1

Si potrebbe sovrascrivere il metodo del vostro oggetto ToString():

public override string ToString() 
{ 
    return string.Format ("{0},{1},{2}", this.number, this.id, this.whatever); 
} 
+0

Ciò è utile solo se conosce esattamente il numero di elementi che desidera inserire nella stringa. string.Join è probabilmente una soluzione migliore. –

+0

Sì, ma dal momento che desidera creare un file csv, gli elementi saranno molto probabilmente gli stessi ogni volta. Non lo so, è una questione di preferenza. –

+0

Ho dedotto dalla domanda che lui vuole sempre gli stessi campi, quindi conosce sicuramente il numero di elementi. Niente di male in questa risposta, anche se non mi piace davvero stravolgere ToString in quanto potrebbe non essere abbastanza generale. +1 da me comunque. – fearofawhackplanet

3

È possibile utilizzare il metodo string.Join per fare qualcosa come string.Join(",", o.Number, o.Id, o.whatever, ...).

modifica: Come diceva digEmAll, string.Join è più veloce di StringBuilder. Usano un'implementazione esterna per la stringa.Join.

il profiling del codice (ovviamente utilizzati con la versione senza i simboli di debug):

class Program 
{ 
    static void Main(string[] args) 
    { 
     Stopwatch sw = new Stopwatch(); 
     string r; 
     int iter = 10000; 

     string[] values = { "a", "b", "c", "d", "a little bit longer please", "one more time" }; 

     sw.Restart(); 
     for (int i = 0; i < iter; i++) 
      r = Program.StringJoin(",", values); 
     sw.Stop(); 
     Console.WriteLine("string.Join ({0} times): {1}ms", iter, sw.ElapsedMilliseconds); 

     sw.Restart(); 
     for (int i = 0; i < iter; i++) 
      r = Program.StringBuilderAppend(",", values); 
     sw.Stop(); 
     Console.WriteLine("StringBuilder.Append ({0} times): {1}ms", iter, sw.ElapsedMilliseconds); 
     Console.ReadLine(); 
    } 

    static string StringJoin(string seperator, params string[] values) 
    { 
     return string.Join(seperator, values); 
    } 

    static string StringBuilderAppend(string seperator, params string[] values) 
    { 
     StringBuilder builder = new StringBuilder(); 
     builder.Append(values[0]); 
     for (int i = 1; i < values.Length; i++) 
     { 
      builder.Append(seperator); 
      builder.Append(values[i]); 
     } 
     return builder.ToString(); 
    } 
} 

string.join preso 2 ms sulla mia macchina e StringBuilder.Append 5ms. Quindi c'è una differenza degna di nota. Grazie a digAmAll per il suggerimento.

+2

'string.Join' è veloce come' StringBuilder' (se non leggermente più veloce) perché entrambi allocano una sola stringa – digEmAll

+0

Il problema con la stringa normale concat (ad esempio usando string1 + = stringa2) è che la stringa originale1 viene gettata via (poiché le stringhe sono immutabili) e la nuova somma di string1 e string2 è puntata da string1 e che non è molto efficiente se eseguita ripetutamente. Tuttavia, come sottolinea anche digEmAll, string.Join ovviamente alloca la stringa solo una volta. Non una volta per ogni elemento dell'array. –

+0

Uno svantaggio di 'string.Join' (fino a .NET 4.0) è che richiede un array di stringhe, costringendovi ad allocarne uno se si dispone solo di un generico' IEnumerable '... in ogni caso .NET 4.0 ha risolto questo problema – digEmAll

1

Se si sta utilizzando .Net 4 è possibile utilizzare il sovraccarico per string.Join che richiede un IEnumerable se li avete in un elenco, troppo:

string.Join(", ", strings); 
6

Un altro approccio è quello di utilizzare la classe CommaDelimitedStringCollection da System .Configuration namespace/assembly. Si comporta come un elenco più ha un metodo ToString sovrascritto che restituisce una stringa separata da virgole.

Pro: più flessibile di un array.

Contro - Non è possibile passare una stringa contenente una virgola.

CommaDelimitedStringCollection list = new CommaDelimitedStringCollection(); 

list.AddRange(new string[] { "Huey", "Dewey" }); 
list.Add("Louie"); 
//list.Add(","); 

string s = list.ToString(); //Huey,Dewey,Louie