Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

stringbuilder versus string concat

Tags:

c#

asp.net

In my project I am looping across a dataview result.

 string html =string.empty;
 DataView dV = data.DefaultView;
 for(int i=0;i< dV.Count;i++)
 {
     DataRowView rv = dV[i];
     html += rv.Row["X"].Tostring();
 }

Number of rows in dV will alway be 3 or 4.

Is it better to use the string concat += opearator or StringBuilder for this case and why?

like image 346
Niraj Choubey Avatar asked Jun 21 '12 07:06

Niraj Choubey


People also ask

Why is StringBuilder better than string concatenation?

Reason being : The String concatenate will create a new string object each time (As String is immutable object) , so it will create 3 objects. With String builder only one object will created[StringBuilder is mutable] and the further string gets appended to it.

Which is faster string concatenation or the StringBuilder class?

Note that regular string concatenations are faster than using the StringBuilder but only when you're using a few of them at a time. If you are using two or three string concatenations, use a string.

Which is better string or StringBuilder?

String is immutable whereas StringBuffer and StringBuilder are mutable classes. StringBuffer is thread-safe and synchronized whereas StringBuilder is not. That's why StringBuilder is faster than StringBuffer.

Is StringBuilder better than +=?

It is always better to use StringBuilder. append to concatenate two string values.


1 Answers

I would use StringBuilder here, just because it describes what you're doing.

For a simple concatenation of 3 or 4 strings, it probably won't make any significant difference, and string concatenation may even be slightly faster - but if you're wrong and there are lots of rows, StringBuilder will start getting much more efficient, and it's always more descriptive of what you're doing.

Alternatively, use something like:

string html = string.Join("", dv.Cast<DataRowView>()
                                .Select(rv => rv.Row["X"]));

Note that you don't have any sort of separator between the strings at the moment. Are you sure that's what you want? (Also note that your code doesn't make a lot of sense at the moment - you're not using i in the loop. Why?)

I have an article about string concatenation which goes into more detail about why it's worth using StringBuilder and when.

EDIT: For those who doubt that string concatenation can be faster, here's a test - with deliberately "nasty" data, but just to prove it's possible:

using System;
using System.Diagnostics;
using System.Text;

class Test
{
    static readonly string[] Bits = { 
        "small string",
        "string which is a bit longer",
        "stirng which is longer again to force yet another copy with any luck"
    };

    static readonly int ExpectedLength = string.Join("", Bits).Length;

    static void Main()        
    {
        Time(StringBuilderTest);
        Time(ConcatenateTest);
    }

    static void Time(Action action)
    {
        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();
        // Make sure it's JITted
        action();
        Stopwatch sw = Stopwatch.StartNew();
        for (int i = 0; i < 10000000; i++)
        {
            action();
        }
        sw.Stop();
        Console.WriteLine("{0}: {1} millis", action.Method.Name,
                          (long) sw.Elapsed.TotalMilliseconds);
    }

    static void ConcatenateTest()
    {
        string x = "";
        foreach (string bit in Bits)
        {
            x += bit;
        }
        // Force a validation to prevent dodgy optimizations
        if (x.Length != ExpectedLength)
        {
            throw new Exception("Eek!");
        }
    }

    static void StringBuilderTest()
    {
        StringBuilder builder = new StringBuilder();
        foreach (string bit in Bits)
        {
            builder.Append(bit);
        }
        string x = builder.ToString();
        // Force a validation to prevent dodgy optimizations
        if (x.Length != ExpectedLength)
        {
            throw new Exception("Eek!");
        }
    }
}

Results on my machine (compiled with /o+ /debug-):

StringBuilderTest: 2245 millis
ConcatenateTest: 989 millis

I've run this several times, including reversing the order of the tests, and the results are consistent.

like image 147
Jon Skeet Avatar answered Oct 08 '22 01:10

Jon Skeet