stringbuilder versus string concat

后端 未结 6 702
醉梦人生
醉梦人生 2020-12-01 11:14

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++)
 {
     Da         


        
6条回答
  •  生来不讨喜
    2020-12-01 11:46

    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()
                                    .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.

提交回复
热议问题