2009-03-17 11 views
1

Je recherche la meilleure façon de créer une chaîne séparée avec une autre dans une boucle. Je veux dire, par exemple, lecteur SQL:Chaîne séparée créée en boucle

StringBuilder sb = new StringBuilder(); 
while(reader.Read()) 
{ 
    sb.Append(reader[0]); 
    sb.Append("<br />"); 
} 
string result = sb.ToString(); 
result = result.Remove(result.LastIndexOf("<br />")); // <- 

ou de créer une chaîne de requête SQL;

StringBuilder sb = new StringBuilder(); 
foreach(string v in values) 
{ 
    sb.Append(v); 
    sb.Append(","); 
} 
string query = sb.ToString() 
query = query.Remove(query.LastIndexOf(",")); // <- 
query = String.Concat("INSERT INTO [foo] ([bar]) VALUES(", query, ")"); 

C'est le meilleur que j'ai trouvé:

List<string> list = new List<string>; 
while(reader.Read()) 
{ 
    list.Add(reader[0]); 
} 
string result = String.Join("<br />", list.ToArray()); 

Edit: Je sais StringBuilder, je ne l'ai pas utilisé ici juste pour une certaine clarté . Mon idée générale n'utilise pas Remove/LastIndexOf!

+0

Quelle est votre question? –

+0

Il cherche le meilleur moyen de créer une chaîne en ajoutant de manière itérative des composants de chaîne ensemble. –

+0

Wow, je suis choqué. –

Répondre

8

Je ne suis pas fan de StringBuilder sauf si vous savez vraiment que vous devez vous soucier de la performance. Il produit un code moche. Je l'écrire de cette façon ...

private IEnumerable<string> ReadAllStrings(DataReader reader) 
{ 
    while(reader.Read()) 
     yield return reader[0]; 
} 


String.Join("<br />", ReadAllStrings(reader).ToArray()); 

Si je faisais beaucoup, je pourrais envisager une méthode d'extension:

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

Ensuite, mon code ressemblerait à ceci:

ReadAllStrings(reader).JoinWith("<br />"); 
+0

Je suis d'accord, Joindre en interne copie toutes les chaînes dans le même tampon, sans nouvelles allocations. – Groo

+0

Donc vous utilisez le même String.Join (String, IEnumerable .ToArray()) aussi - Je pense que c'est le meilleur moyen, n'est-ce pas? – abatishchev

+0

Oui, je pense que c'est la meilleure façon. Mais dans votre exemple, vous créez deux copies de la collection. Un pour la liste et un pour ToArray(). Dans le mien, vous ne créez qu'un seul tableau. –

5

Comment est sur:

StringBuilder builder; 
while (reader.Read()) 
{ 
    if(builder == null) 
    { 
     builder = new StringBuilder(reader[0]); 
    } 
    else 
    { 
     builder.Append("<br />"); 
     builder.Append(reader[0]); 
    } 
} 
string result = builder.ToString(); 
+0

On dirait bien! Je pense que c'est la meilleure solution 'classique', je veux dire pour .NET 2.0, sans utiliser d'extensions, etc. – abatishchev

2

Ceci est juste une combinaison de plusieurs des meilleures idées montré:

public static class Extensions 
{ 

    public static string JoinStrings(this DataReader reader, int ColumnIndex, string delimiter) 
    { 
     var result = new StringBuidler(); 
     var delim = String.Empty; 
     while (reader.Read()) 
     { 
      result.Append(delim).Append(reader[ColumnIndex].ToString()); 
      delim = delimiter; 
     } 
     return result.ToString(); 
    } 
} 

Maintenant, tout ce que vous avez à faire est d'appeler comme ceci:

string result = reader.JoinStrings(0, "<br/>"); 
1

Une autre solution .Net 2.0 - changer l'ordre:

reader.Read(); 
StringBuilder sb = new StringBuilder(reader[0]); 
while(reader.Read()) 
{ 
    sb.Append("<br />"); 
    sb.Append(reader[0]); 
} 
string result = sb.ToString(); 
+0

Cela échouera si la requête n'a renvoyé aucune ligne, mais tout ce dont elle a vraiment besoin est une autre instruction if, ce n'est donc pas si grave. –

+0

en effet ce serait, mais beaucoup de solutions ici feraient la même chose. Il n'y a pas non plus de conversion de type de données à partir de ce que le lecteur retourne, et il est inutile d'attribuer la valeur de StringReader au résultat, mais cela montre le point. – cjk

1
public class Separator 
{ 

    private string sep; 
    private bool first = true; 

    public Separator(string sep) 
    { 
     this.sep = sep; 
    } 

    public virtual string ToString() 
    { 
     string reply = first ? "" : sep; 
     first = false; 
     return reply; 
    } 
} 

var sep = new Separator("<br/>"); 
var builder = new StringBuilder(); 
while (reader.Read()) 
{ 
    builder.Append (sep.ToString()) ; 
    builder.Append (reader[0]) ; 
} 
+0

Vous avez eu un bug, mais je l'ai corrigé. –