10

string to build up using keyvaluepair is like this: "name1=v1&name2=v2&name3=v3"

what i am doing:

var sb = new StringBuilder();

foreach (var name in nameValues)
{
            sb.AppendFormat("{0}={1}&", name.Key, name.Value);
 } 

//remove last '&' sign, this is what i think is ugly
sb.ToString().Remove(lastIndex);

any elegant way to avoid the last removal statement of '&' sign?

Yacoby
  • 54,544
  • 15
  • 116
  • 120
Benny
  • 8,547
  • 9
  • 60
  • 93

7 Answers7

18
var joined =
    String.Join("&", nameValues.Select(n => n.Key + "=" + n.Value).ToArray());

Given that we're not concatenating to one big string (we're producing many small strings) concatenation carries no performace penalties in this case. And in .NET strings are length prefixed anyway so the whole concatenation performance issue is less relevant than in C. String.Join() is very fast as well, faster than StringBuilder.

TLDR: Use String.Join()

Tamas Czinege
  • 118,853
  • 40
  • 150
  • 176
5

Take a look here: How to build a query string for a URL in C#?; Quoting:

private string ToQueryString(NameValueCollection nvc)
{
    return "?" + 
        string.Join("&", 
            Array.ConvertAll(
                nvc.AllKeys, 
                key => String.Format("{0}={1}", HttpUtility.UrlEncode(key),
                HttpUtility.UrlEncode(nvc[key]))));
}
Community
  • 1
  • 1
Rubens Farias
  • 57,174
  • 8
  • 131
  • 162
4
foreach (var name in nameValues)
    {
        if (sb.Length > 0) sb.Append("&");
                sb.AppendFormat("{0}={1}", name.Key, name.Value);
     }

Just add "&" when needed, do not remove it from end.

Nick43
  • 71
  • 2
  • 3
    And if speed is a concern, use sb.Append(name.Key).Append("=").Append(name.Value); – Will Jan 06 '10 at 11:13
3

Here's another approach which I've sometimes used:

var sb = new StringBuilder();
string prefix = "";
foreach (var name in nameValues)
{
    sb.Append(prefix);
    prefix = "&";
    sb.AppendFormat("{0}={1}", name.Key, name.Value);
}

It's just a way of prepending & before every pair other than the first one without using a conditional test.

If you want to use your original idea of trimming the StringBuilder by the way, I'd suggest the following code instead:

sb.Length--; // Remove the last character
return sb.ToString();
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
3

I tend to use this, utilising the fact you can truncate a string builder with a decrement on the length property:

var sb = new StringBuilder();

foreach (var name in nameValues)
{
    sb.AppendFormat("{0}={1}&", name.Key, name.Value);
} 

if (sb.Length > 0) sb.Length--;
Rob Levine
  • 40,328
  • 13
  • 85
  • 111
1

Well at least you can remove the & sign before the ToString() call by doing --sb.Length;

Gregory Pakosz
  • 69,011
  • 20
  • 139
  • 164
0
var sb = new StringBuilder();

sb.AppendFormat("{0}={1}", nameValues[0].Key, nameValues[0].Value);

for (int i = 1; i < nameValues.Count; i++)
{
        sb.AppendFormat("&{0}={1}", nameValues[i].Key, nameValues[i].Value);
} 
Oded
  • 489,969
  • 99
  • 883
  • 1,009
  • Small typo on the first AppendFormat - it doesn't need the '&'. This method works great if there is guaranteed to be at least one entry. – Will Jan 06 '10 at 11:05