== Why is this an issue?

Concatenating multiple string literals or strings using the `+` operator creates a new string object for each concatenation. This can lead to a large number of intermediate string objects and can be inefficient. The `StringBuilder` class is more efficient than string concatenation, especially when the operator is repeated over and over as in loops.

== How to fix it

Replace string concatenation with `StringBuilder`.

=== Code examples

==== Noncompliant code example

[source,csharp,diff-id=1,diff-type=noncompliant]
----
string str = "";
for (int i = 0; i < arrayOfStrings.Length ; ++i)
{
  str = str + arrayOfStrings[i];
}
----

==== Compliant solution

[source,csharp,diff-id=1,diff-type=compliant]
----
StringBuilder bld = new StringBuilder();
for (int i = 0; i < arrayOfStrings.Length; ++i)
{
  bld.Append(arrayOfStrings[i]);
}
string str = bld.ToString();
----

== Resources

=== Documentation

* Microsoft Learn - https://learn.microsoft.com/en-us/dotnet/api/system.text.stringbuilder[StringBuilder Class]

=== Benchmarks

[options="header"]
|===
| Method               | Runtime              | Mean         | Standard Deviation     | Allocated
| StringConcatenation  | .NET 9.0             | 50,530.75 us | 2,699.189 us           | 586280.70 KB
| StringBuilder        | .NET 9.0             |     82.31 us |     3.387 us           |    243.79 KB
| StringConcatenation  | .NET Framework 4.8.1 | 37,453.72 us | 1,543.051 us           | 586450.38 KB
| StringBuilder        | .NET Framework 4.8.1 |    178.32 us |     6.148 us           |    244.15 KB
|===

==== Glossary

* https://en.wikipedia.org/wiki/Arithmetic_mean[Mean]
* https://en.wikipedia.org/wiki/Standard_deviation[Standard Deviation]

The results were generated by running the following snippet with https://github.com/dotnet/BenchmarkDotNet[BenchmarkDotNet]:

[source,csharp]
----
[Params(10_000)]
public int Iterations;

[Benchmark]
public void StringConcatenation()
{
    string str = "";
    for (int i = 0; i < Iterations; i++)
    {
        str = str + "append";
    }
}

[Benchmark]
public void StringBuilder()
{
    StringBuilder builder = new StringBuilder();
    for (int i = 0; i < Iterations; i++)
    {
        builder.Append("append");
    }
    _ = builder.ToString();
}
----

Hardware Configuration:

[source]
----
BenchmarkDotNet v0.14.0, Windows 10 (10.0.19045.5247/22H2/2022Update)
12th Gen Intel Core i7-12800H, 1 CPU, 20 logical and 14 physical cores
  [Host]               : .NET Framework 4.8.1 (4.8.9282.0), X64 RyuJIT VectorSize=256
  .NET 9.0             : .NET 9.0.0 (9.0.24.52809), X64 RyuJIT AVX2
  .NET Framework 4.8.1 : .NET Framework 4.8.1 (4.8.9282.0), X64 RyuJIT VectorSize=256
----

ifdef::env-github,rspecator-view[]

'''
== Implementation Specification
(visible only on this page)

include::../message.adoc[]

'''
== Comments And Links
(visible only on this page)

include::../comments-and-links.adoc[]

endif::env-github,rspecator-view[]
