2011-02-03 6 views
32

J'ai un objet qui contient de nombreuses valeurs, certaines d'entre elles (pas toutes les valeurs de l'objet) doivent être placées dans une chaîne csv. Mon approche était la suivante:Créer des chaînes séparées par des virgules C#?

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

D'une manière ou d'une autre, je pense qu'il y a une façon meilleure, plus élégante?

+0

D'une manière générale, il est considéré comme moins efficace de concaténer des chaînes avec le symbole '+'. Cela crée plus d'objets à ramasser. –

+0

[séparation manuelle des virgules par rapport à la classe cool CommaDelimitedStringCollection!] (Http://izlooite.blogspot.com/2009/12/manual-comma-separation-versus-cool.html) –

Répondre

73

Si vous mettez toutes vos valeurs dans un tableau, vous pouvez au moins utiliser string.Join.

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

Vous pouvez également utiliser la surcharge de string.Join qui prend params string comme second paramètre comme celui-ci:

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

+1 pour l'utilisation d'un tableau entre le code est plus lisible lorsqu'il y a plus que "quelques" valeurs. – Bazzz

+0

@Bazzz - Oui, cela peut vite devenir compliqué si vous entrez plus de 10 paramètres dans l'appel de la méthode de jointure. Je pense que la première approche est la plus propre, mais pour quelques valeurs, la deuxième approche est également acceptable. –

+0

Pourquoi deux downvotes sur cette réponse? Une raison serait appréciée pour que tout le monde sache ce que vous pensez être le problème avec cette réponse. –

1

Vous pouvez remplacer votre méthode objet ToString():

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

Ceci n'est utile que s'il connaît exactement le nombre d'éléments qu'il veut mettre dans la chaîne. string.Join est probablement un meilleur ajustement. –

+0

Oui, mais comme il veut créer un fichier csv, les éléments seront probablement les mêmes à chaque fois. Je ne sais pas, c'est une question de préférence. –

+0

J'ai supposé à partir de la question qu'il veut toujours les mêmes champs donc il sait certainement le nombre d'éléments. Rien ne cloche avec cette réponse, bien que je n'aime pas vraiment surcharger ToString ici car il peut ne pas être assez général. +1 de ma part de toute façon. – fearofawhackplanet

3

Vous pouvez utiliser la méthode string.Join pour faire quelque chose comme string.Join(",", o.Number, o.Id, o.whatever, ...).

edit: Comme le dit digEmAll, string.Join est plus rapide que StringBuilder. Ils utilisent une implémentation externe pour la chaîne.Join.

Code de profil (des cours d'exécution dans la version sans symboles de débogage):

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 a 2ms sur ma machine et StringBuilder.Append 5ms. Il y a donc une différence notable. Merci à digAmAll pour l'indice.

+2

'string.Join' est aussi rapide que' StringBuilder' (sinon légèrement plus rapide) car ils n'allouent tous les deux qu'une seule chaîne – digEmAll

+0

Le problème avec la concat de chaîne normale (par exemple en utilisant string1 + = string2) est que la chaîne originale1 est rejetée (puisque les chaînes sont immuables), et que la nouvelle somme de chaîne1 et chaîne2 est pointée par chaîne1, ce qui n'est pas très efficace si elle est répétée. Cependant, comme le montre digEmAll, string.Join bien sûr, n'allouer qu'une seule fois la chaîne. Pas une fois pour chaque élément du tableau. –

+0

Un inconvénient de 'string.Join' (jusqu'à .NET 4.0) est qu'il nécessite un tableau de chaînes, vous obligeant à en allouer un si vous avez seulement un générique' IEnumerable '... de toute façon. NET 4.0 a résolu ce problème – digEmAll

1

Si vous utilisez .Net 4, vous pouvez utiliser la surcharge pour string.Join qui prend un IEnumerable si vous les avez dans une liste aussi:

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

Une autre approche consiste à utiliser la classe CommaDelimitedStringCollection du système Espace de noms/assembly .Configuration. Il se comporte comme une liste et possède une méthode ToString surchargée qui renvoie une chaîne séparée par des virgules.

Avantages - Plus flexible qu'un tableau. Contre - Vous ne pouvez pas passer une chaîne contenant une virgule.

CommaDelimitedStringCollection list = new CommaDelimitedStringCollection(); 

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

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