Using Concat to concatenate array of strings

Asked

Viewed 488 times

4

I was seeing about strings and that they are immutable and cannot be added to them in quantity otherwise they will be very slow.

The recommendation is to use the StringBuilder. But I also saw that there’s a version of Concat() accepting an array.

It wouldn’t be the case to use it?

  • 1

    You saw I used the method group passing in the Time()? http://answall.com/q/189905/101. In this case the group has only one method, but is still a group.

  • @Got it. It was pretty clear, thanks!

1 answer

6

Probably what you read was a "good practice" (which I am a critic of). I myself fall into this nonsense when I write because we do not always have time to explain all the details, but if one accepts someone’s statement without a context is just following such "good practices" and may not have the expected result, how that can be the opposite and become a bad practice.

In fact the StringBuilder is recommended when you have to add several strings in one. But if this operation is the only one and you don’t have to do other actions in the loop then you don’t have to use the StringBuilder, because I think the Concat() uses a StringBuilder internally, so you get a code one Liner.

But let’s be sure and make one benchmark:

using System;
using static System.Console;
using System.Diagnostics;
using System.Text;

public class Program {
    const int Limit = 100000;
    static int[] dataInt = new int[Limit];
    static string[] dataString = new string[Limit];

    public static void Main() {
        for (int i = 0; i < Limit; i++) {
            dataInt[i] = i;
            dataString[i] = i.ToString();
        }
        Time(ConcatenationInt);
        Time(JunctionInt);
        Time(BuilderInt);
        Time(AdditionInt);
        Time(ConcatenationString);
        Time(JunctionString);
        Time(BuilderString);
        Time(AdditionString);
    }

    static void Time(Func<int> action) {
        var sw = Stopwatch.StartNew();
        int result = action();
        sw.Stop();
        WriteLine($"{result} - {sw.ElapsedTicks:000,000,000} - {action.Method.Name}");
        GC.Collect();
        GC.WaitForPendingFinalizers();
    }

    static int AdditionInt() {
        var tmp = "";
        for (int i = 0; i < Limit; i++) tmp += dataInt[i];
        return tmp.Length;            
    }

    static int AdditionString() {
        var tmp = "";
        for (int i = 0; i < Limit; i++) tmp += dataString[i];
        return tmp.Length;
    }

    static int ConcatenationInt() => string.Concat(dataInt).Length;

    static int ConcatenationString() => string.Concat(dataString).Length;

    static int JunctionInt() => string.Join("", dataInt).Length;

    static int JunctionString() => string.Join("", dataString).Length;

    static int BuilderInt() {
        var tmp = new StringBuilder();
        for (int i = 0; i < Limit; i++) tmp.Append(dataInt[i]);
        return tmp.Length;            
    }

    static int BuilderString() {
        var tmp = new StringBuilder();
        for (int i = 0; i < Limit; i++) tmp.Append(dataString[i]);
        return tmp.Length;            
    }
}

Behold working in the ideone. And in the .NET Fiddle. Also put on the Github for future reference.

The ideal is to test on your machine with nothing affecting the execution. Tests in shared environments like the ones used above are not valid. I tried to minimize the effect of GC, but there’s no way in this restricted memory environment.

The conclusion that can be drawn is that in this case the concatenation is great, the junction also, and the construction of the string is an almost as good option, only the individual addition is that it is tragic.

The code of Concat()can be seen and he does something even a little bit smarter than the StringBuilder. No . NET Core.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.