66 votes

Créer des chaînes de caractères séparées par des virgules en C#

J'ai un objet qui contient de nombreuses valeurs, et certaines d'entre elles (pas toutes les valeurs de l'objet) doivent être placées dans un fichier de type CSV chaîne. Mon approche était la suivante :

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

Existe-t-il un meilleur moyen, plus élégant ?

0 votes

En général, il est considéré comme moins efficace de concaténer des chaînes de caractères avec la fonction + symbole. Cela crée plus d'objets à collecter.

135voto

Øyvind Bråthen Points 25211

Si vous mettez toutes vos valeurs dans un tableau, au moins vous pouvez 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 deuxième paramètre comme ceci :

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

0 votes

+1 pour l'utilisation d'un tableau entre les deux, ce qui rend le code plus lisible lorsqu'il y a plus que "quelques" valeurs.

0 votes

@Bazzz - Oui, cela peut rapidement devenir désordonné 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 seconde est également acceptable.

0 votes

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 de cette réponse.

15voto

grysik44 Points 233

Une autre approche consiste à utiliser la classe CommaDelimitedStringCollection de l'espace de noms/assemblage System.Configuration. Elle 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.

Pour - 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

5voto

jb_ Points 763

Vous pouvez utiliser le string.Join pour faire quelque chose comme string.Join(",", o.Number, o.Id, o.whatever, ...) .

edit : Comme digEmAll l'a dit, string.Join est plus rapide que StringBuilder. Ils utilisent une implémentation externe pour le string.Join.

Profilage du code (bien sûr, exécuté en 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 pris 2ms sur ma machine et StringBuilder.Append 5ms. Il y a donc une différence notable. Merci à digAmAll pour l'astuce.

2 votes

string.Join est aussi rapide que StringBuilder (si ce n'est légèrement plus rapide) parce qu'ils allouent tous deux une seule chaîne de caractères

0 votes

Le problème avec la concaténation normale de chaînes (par exemple en utilisant string1 += string2) est que la chaîne originale string1 est jetée (puisque les chaînes sont immuables), et la nouvelle somme de string1 et string2 est pointée par string1, et ce n'est pas très efficace si cela est fait de façon répétée. Cependant, comme digEmAll le fait également remarquer, string.Join n'alloue bien sûr la chaîne qu'une seule fois. Pas une fois pour chaque élément du tableau.

0 votes

L'un des inconvénients de string.Join (jusqu'à .NET 4.0) est qu'elle nécessite un tableau de chaînes de caractères, ce qui vous oblige à en allouer un si vous ne disposez que d'un tableau de chaînes générique. IEnumerable<string> ... de toute façon, .NET 4.0 a corrigé ce problème.

4voto

Jackson Pope Points 9294

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);

1voto

Dimitris Tavlikos Points 7908

Vous pouvez surcharger la méthode ToString() de votre objet :

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

0 votes

Cela n'est utile que s'il connaît exactement le nombre d'éléments qu'il veut mettre dans la chaîne de caractères. string.Join est probablement plus adapté.

0 votes

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

0 votes

J'ai supposé, d'après la question, qu'il voulait toujours les mêmes champs et qu'il connaissait donc bien le nombre d'éléments. Il n'y a rien de mal à cette réponse, même si je n'aime pas vraiment la surcharge de ToString ici, car elle n'est peut-être pas assez générale. +1 de ma part en tout cas.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X