What is the most appropriate way to concatenate strings?

Asked

Viewed 28,968 times

31

There are different methods for concatenating strings, such as

  • Concatenating with the operator "abc" + str
  • Formatting String.Format("abc{0}", str);
  • Using the Stringbuilder new StringBuilder("abc").Append(str);
  • Using the String Concat method String.Concat("abc", str);

In what situation should I use each one? What can be more efficient in each case?

  • Take a look at this link, has performance comparison between the ways of concatenating string.

  • In C# 6.0 they added a new form of concatenation, through the '$'. Example: string str = "world"; $"Hello {str}"; Output: Hello world

4 answers

36


First of all, what is literal constant?

Literal constant is the representation of a value of a string in the source code, example:

"isto é uma constante literal"

Another example:

var str = "foo";

In this example str is a string and "foo" one literal constant.

In our day-to-day life we don’t need to emphasize this difference, but when we talk about performance over strings it’s critical to differentiate. Because literal constants are values that are directly present in the source code this gives the compiler the opportunity to optimize these operations (such as concatenating at compile time).

Operator +

"A temperatura em " + cidade + " é de " + temperatura;

Pro:

  • If concatenated literal constants the concatenation is performed at compile time.
  • Is considered the standard.

Against:

  • Barely readable; difficult to edit.

string. Concat

string.Concat("A temperatura em ", cidade, " é de ", temperatura);

In terms of performance is identical to the operator + (except in the case of literal constants).

string. Format

string.Format("A temperatura em {0} é de {1}", cidade, temperatura);

Pro:

  • Preferred by many when formatting concatenation (more readable).
  • Easy to use a string concatenated several times in the original string (just repeat the index).

Against:

  • Little performatic.
  • An execution (not compilation) error is generated if an invalid number of parameters to be concatenated is passed.
  • In a string with many concatenations, it may not be very friendly to keep keeping the numbers of the concatenation indices.

Stringbuilder

new StringBuilder("A temperatura em ").Append(cidade).Append(" é de ").Append(temperatura);

Stringbuilder is a specific class for string construction. The big difference from the previous methods is that while the traditional type System.String is an immutable object, that is, every operation creates a new string, already the Stringbuilder is changeable, making it the most performative in scenarios involving many operations (read concatenations in loops).

It is important to note that the use in the above example is a case in which nay whether to use Stringbuilder.

Considerations

We as programmers like this kind of subject matter very much but the reality is that worrying about performance in trivial string concatenations is the call micro optimization (notice the bad connotation).

As a general rule, I particularly follow:

  • I try to use simple concatenation, via operator +.
  • If by chance the project I’m working on takes another way, string.Concat for example, I will use it. Consistency is something important.
  • When a large number of concatenations of literal constants is done prejudge by the operator +. This concatenation will be done at compile time saving precious processing cycles.
  • When the strings involved are large, multiple operations, loop operations, in short, when a heavy job is done on strings use Stringbuilder. Do not use it for trivial work.
  • What do you mean "uncomplicated"?

  • @Franciscojunior means to have low performance; a poor performance.

  • I imagined, although I did not know this term. Would it not be clearer to the reader if it was written "low performance"?

9

Since every string can be considered an array of characters, concatenating strings in the classic way is very costly. For every + used, a copy of a new string is generated in memory. In the case of C#, as explained below, concatenations using + are translated to String.Concat().

The best way is to use the class StringBuilder along with the method Append. See how it is to implement a Stringbuilder class to understand how it improves concatenation performance: http://dteixeira.com/847/exploring-arrays-introduction/

When to use: Concatenations within loops, when the amount of concatenations is not predicted.

The String.Format() is only suitable for placeholder replacement, such as: String.Format("Olá {0}, você tem {1} mensagens.", "Beto", 23);. By design, this path is not recommended for concatenation, as it makes use of Replaces, which is very costly for this purpose.

The String.Concat() has a performance equal to concatenate with a +signal, as it only encapsulates the operand += so to speak.

For the following code:

string a = "Um";
string b = "dois";
string c = "Tres";
string d = a + b + c;

It will be interpreted in the compiler as:

string a = "Um";
string b = "dois";
string c = "Tres";
string d = String.Concat(a, b, c);

When to use: If you need to combine two arrays or Lists into one variable. As you can extend this method to other input types.

If you want to explore the details of string concatenation, there is a detailed article on this.

  • 1

    There is a cost for instantiating a Stringbuilder that makes this approach not recommended (in terms of performance) to concatenate a few strings.

  • 1

    Yes, Stringbuilder is good when we are dealing with concatenations within loops. Otherwise, using Concat is better. I will add this edition to the reply.

  • 1

    Options 2 and 3 can be combined into one using StringBuilder.AppendFormat()

  • No new string is created for each +. The + are translated by the compiler into calls to String.Concat which can receive several parameters.

  • The String.Format does not use Replace. Usa StringBuilder.AppendFormat which also does not use Replace.

  • Paulo Morgado, I’m interested in knowing some source where you can read about how String.Concat works internally?

  • @Dorival you can decompile the class System.String to get an idea of how their methods were implemented.

  • Yes Humberto, I just wanted to know if anyone had anything out of the pocket :)

Show 3 more comments

6

When in doubt, test...

Times obtained with the code below (is a Tosko benchmark and varies according to the number of iterations, but you can get an idea):

Testing Testarsoma... 37,076 ms

Testing Testarconcat... 36,346 ms

Testing Testarstringbuilder... 3 ms

Testing Testarstream... 10 ms

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

namespace ConsoleApplication1
{

    public class Program
    {

        private const int LOOP_COUNT = 100000;

        public static void Main(string[] args)
        {
            Testar(TestarSoma);
            Testar(TestarConcat);
            Testar(TestarStringBuilder);
            Testar(TestarStream);
        }

        private static void Testar(Func<string> metodo)
        {
            var sw = new Stopwatch();

            Console.Write("Testando {0}... ", metodo.Method.Name);
            sw.Start();
            metodo();
            sw.Stop();
            Console.WriteLine("{0:N0} ms", sw.ElapsedMilliseconds);
        }

        private static string TestarSoma()
        {
            var a = "Um";
            var b = "Dois";
            var c = "Três";
            var d = "";

            for (var ct = 0; ct <= LOOP_COUNT; ct++)
            {
                d += a + b + c;
            }

            return d;
        }

        private static string TestarConcat()
        {
            var a = "Um";
            var b = "Dois";
            var c = "Três";
            var d = "";

            for (var ct = 0; ct <= LOOP_COUNT; ct++)
            {
                d = string.Concat(d, a, b, c);
            }

            return d;
        }

        private static string TestarStringBuilder()
        {
            var a = "Um";
            var b = "Dois";
            var c = "Três";
            var d = new StringBuilder();

            for (var ct = 0; ct <= LOOP_COUNT; ct++)
            {
                d.Append(a);
                d.Append(b);
                d.Append(c);
            }

            return d.ToString();
        }

        private static string TestarStream()
        {
            var a = "Um";
            var b = "Dois";
            var c = "Três";

            using (var ms = new MemoryStream())
            using (var sw = new StreamWriter(ms))
            {
                for (var ct = 0; ct <= LOOP_COUNT; ct++)
                {
                    sw.Write(a);
                    sw.Write(b);
                    sw.Write(c);
                }

                sw.Flush();
                ms.Seek(0, SeekOrigin.Begin);

                using (var sr = new StreamReader(ms))
                {
                    return sr.ReadToEnd();
                }
            }
        }

    }
}

1

No doubt, use concat() or join() to join small pieces of string.

To concatenate something like several large phrases/lines (whether inside or outside a loop) consider using StringBuilder.

Just use the + if it is to concatenate LETTERS or few words.

Look at this page, TEST WITH YOUR STRING and draw its conclusion.

Browser other questions tagged

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