C#idiomatic C#
concatenatecsharp/fundamentals/strings/common-tasks

Language

Concatenate strings in C#

Learn how to combine strings in C# with the + operator, string interpolation, string.Concat, string.Join, and StringBuilder, and how to choose between them.

  • page csharp/fundamentals/strings/common-tasks/concatenate
  • updated 06/24/2026

Concatenation appends one string to the end of another to produce a new string. C# gives you several ways to concatenate, and the best choice depends on whether you're joining a fixed set of values or a collection, or building a string piece by piece in a loop.

Concatenate string literals

When you concatenate string literals or constants with +, the compiler joins them at compile time. Splitting a long literal across several lines improves readability in source without any run-time cost:

sample · csharpdocs/csharp/fundamentals/strings/common-tasks/snippets/concatenate/Program.csLiterals

csharp
using System.Text;

namespace ConcatenateStrings;

public static class Program
{
    public static void Main()
    {
        CombineLiterals();
        Console.WriteLine();
        UseOperators();
        Console.WriteLine();
        UseInterpolation();
        Console.WriteLine();
        UseConcatAndJoin();
        Console.WriteLine();
        UseStringBuilder();
    }

    private static void CombineLiterals()
    {
        // <Literals>
        // The compiler joins adjacent string literals at compile time,
        // so splitting a long literal across lines has no run-time cost.
        string message =
            "This is the first sentence of a longer message. " +
            "This is the second sentence. " +
            "This is the third and final sentence.";

        Console.WriteLine(message);
        // => This is the first sentence of a longer message. This is the second sentence. This is the third and final sentence.
        // </Literals>
    }

    private static void UseOperators()
    {
        // <Operators>
        string name = "Alex";
        string day = "Monday";

        // Use + to build a string from variables and literals.
        string greeting = "Hello " + name + ". Today is " + day + ".";
        Console.WriteLine(greeting);
        // => Hello Alex. Today is Monday.

        // Use += to append to an existing string.
        greeting += " How are you today?";
        Console.WriteLine(greeting);
        // => Hello Alex. Today is Monday. How are you today?
        // </Operators>
    }

    private static void UseInterpolation()
    {
        // <Interpolation>
        string name = "Alex";
        string day = "Monday";

        // String interpolation reads better than a chain of + operators.
        string greeting = $"Hello {name}. Today is {day}.";
        Console.WriteLine(greeting);
        // => Hello Alex. Today is Monday.
        // </Interpolation>
    }

    private static void UseConcatAndJoin()
    {
        // <ConcatJoin>
        string[] words = ["The", "quick", "brown", "fox"];

        // Concat joins the sequence with no separator.
        string runTogether = string.Concat(words);
        Console.WriteLine(runTogether);
        // => Thequickbrownfox

        // Join places a separator between each element.
        string sentence = string.Join(' ', words);
        Console.WriteLine(sentence);
        // => The quick brown fox
        // </ConcatJoin>
    }

    private static void UseStringBuilder()
    {
        // <StringBuilder>
        // StringBuilder builds a string in place, which suits loops
        // that append many pieces.
        var builder = new StringBuilder();
        for (int i = 1; i <= 3; i++)
        {
            builder.AppendLine($"Line {i}");
        }

        Console.Write(builder.ToString());
        // => Line 1
        // => Line 2
        // => Line 3
        // </StringBuilder>
    }
}

Use the + and += operators

To combine string variables, use the + operator to produce a new string, or += to append to an existing one. The + operator is intuitive, and the compiler copies the string content only once even when you chain several operators in a single expression:

sample · csharpdocs/csharp/fundamentals/strings/common-tasks/snippets/concatenate/Program.csOperators

csharp
using System.Text;

namespace ConcatenateStrings;

public static class Program
{
    public static void Main()
    {
        CombineLiterals();
        Console.WriteLine();
        UseOperators();
        Console.WriteLine();
        UseInterpolation();
        Console.WriteLine();
        UseConcatAndJoin();
        Console.WriteLine();
        UseStringBuilder();
    }

    private static void CombineLiterals()
    {
        // <Literals>
        // The compiler joins adjacent string literals at compile time,
        // so splitting a long literal across lines has no run-time cost.
        string message =
            "This is the first sentence of a longer message. " +
            "This is the second sentence. " +
            "This is the third and final sentence.";

        Console.WriteLine(message);
        // => This is the first sentence of a longer message. This is the second sentence. This is the third and final sentence.
        // </Literals>
    }

    private static void UseOperators()
    {
        // <Operators>
        string name = "Alex";
        string day = "Monday";

        // Use + to build a string from variables and literals.
        string greeting = "Hello " + name + ". Today is " + day + ".";
        Console.WriteLine(greeting);
        // => Hello Alex. Today is Monday.

        // Use += to append to an existing string.
        greeting += " How are you today?";
        Console.WriteLine(greeting);
        // => Hello Alex. Today is Monday. How are you today?
        // </Operators>
    }

    private static void UseInterpolation()
    {
        // <Interpolation>
        string name = "Alex";
        string day = "Monday";

        // String interpolation reads better than a chain of + operators.
        string greeting = $"Hello {name}. Today is {day}.";
        Console.WriteLine(greeting);
        // => Hello Alex. Today is Monday.
        // </Interpolation>
    }

    private static void UseConcatAndJoin()
    {
        // <ConcatJoin>
        string[] words = ["The", "quick", "brown", "fox"];

        // Concat joins the sequence with no separator.
        string runTogether = string.Concat(words);
        Console.WriteLine(runTogether);
        // => Thequickbrownfox

        // Join places a separator between each element.
        string sentence = string.Join(' ', words);
        Console.WriteLine(sentence);
        // => The quick brown fox
        // </ConcatJoin>
    }

    private static void UseStringBuilder()
    {
        // <StringBuilder>
        // StringBuilder builds a string in place, which suits loops
        // that append many pieces.
        var builder = new StringBuilder();
        for (int i = 1; i <= 3; i++)
        {
            builder.AppendLine($"Line {i}");
        }

        Console.Write(builder.ToString());
        // => Line 1
        // => Line 2
        // => Line 3
        // </StringBuilder>
    }
}

Use string interpolation

To embed computed expressions in a string, prefer string interpolation over positional placeholders like the {0} and {1} tokens that System.String.Format inherits from C-style formatting. Interpolation places each expression inline where its value appears, so the result string stays readable and you can't misalign an argument:

sample · csharpdocs/csharp/fundamentals/strings/common-tasks/snippets/concatenate/Program.csInterpolation

csharp
using System.Text;

namespace ConcatenateStrings;

public static class Program
{
    public static void Main()
    {
        CombineLiterals();
        Console.WriteLine();
        UseOperators();
        Console.WriteLine();
        UseInterpolation();
        Console.WriteLine();
        UseConcatAndJoin();
        Console.WriteLine();
        UseStringBuilder();
    }

    private static void CombineLiterals()
    {
        // <Literals>
        // The compiler joins adjacent string literals at compile time,
        // so splitting a long literal across lines has no run-time cost.
        string message =
            "This is the first sentence of a longer message. " +
            "This is the second sentence. " +
            "This is the third and final sentence.";

        Console.WriteLine(message);
        // => This is the first sentence of a longer message. This is the second sentence. This is the third and final sentence.
        // </Literals>
    }

    private static void UseOperators()
    {
        // <Operators>
        string name = "Alex";
        string day = "Monday";

        // Use + to build a string from variables and literals.
        string greeting = "Hello " + name + ". Today is " + day + ".";
        Console.WriteLine(greeting);
        // => Hello Alex. Today is Monday.

        // Use += to append to an existing string.
        greeting += " How are you today?";
        Console.WriteLine(greeting);
        // => Hello Alex. Today is Monday. How are you today?
        // </Operators>
    }

    private static void UseInterpolation()
    {
        // <Interpolation>
        string name = "Alex";
        string day = "Monday";

        // String interpolation reads better than a chain of + operators.
        string greeting = $"Hello {name}. Today is {day}.";
        Console.WriteLine(greeting);
        // => Hello Alex. Today is Monday.
        // </Interpolation>
    }

    private static void UseConcatAndJoin()
    {
        // <ConcatJoin>
        string[] words = ["The", "quick", "brown", "fox"];

        // Concat joins the sequence with no separator.
        string runTogether = string.Concat(words);
        Console.WriteLine(runTogether);
        // => Thequickbrownfox

        // Join places a separator between each element.
        string sentence = string.Join(' ', words);
        Console.WriteLine(sentence);
        // => The quick brown fox
        // </ConcatJoin>
    }

    private static void UseStringBuilder()
    {
        // <StringBuilder>
        // StringBuilder builds a string in place, which suits loops
        // that append many pieces.
        var builder = new StringBuilder();
        for (int i = 1; i <= 3; i++)
        {
            builder.AppendLine($"Line {i}");
        }

        Console.Write(builder.ToString());
        // => Line 1
        // => Line 2
        // => Line 3
        // </StringBuilder>
    }
}

When every interpolated expression is itself a constant string, you can assign the interpolated result to a const string.

Join a collection of strings

To combine the elements of a collection, use System.String.Concat to join them with no separator, or System.String.Join to place a separator between each element:

sample · csharpdocs/csharp/fundamentals/strings/common-tasks/snippets/concatenate/Program.csConcatJoin

csharp
using System.Text;

namespace ConcatenateStrings;

public static class Program
{
    public static void Main()
    {
        CombineLiterals();
        Console.WriteLine();
        UseOperators();
        Console.WriteLine();
        UseInterpolation();
        Console.WriteLine();
        UseConcatAndJoin();
        Console.WriteLine();
        UseStringBuilder();
    }

    private static void CombineLiterals()
    {
        // <Literals>
        // The compiler joins adjacent string literals at compile time,
        // so splitting a long literal across lines has no run-time cost.
        string message =
            "This is the first sentence of a longer message. " +
            "This is the second sentence. " +
            "This is the third and final sentence.";

        Console.WriteLine(message);
        // => This is the first sentence of a longer message. This is the second sentence. This is the third and final sentence.
        // </Literals>
    }

    private static void UseOperators()
    {
        // <Operators>
        string name = "Alex";
        string day = "Monday";

        // Use + to build a string from variables and literals.
        string greeting = "Hello " + name + ". Today is " + day + ".";
        Console.WriteLine(greeting);
        // => Hello Alex. Today is Monday.

        // Use += to append to an existing string.
        greeting += " How are you today?";
        Console.WriteLine(greeting);
        // => Hello Alex. Today is Monday. How are you today?
        // </Operators>
    }

    private static void UseInterpolation()
    {
        // <Interpolation>
        string name = "Alex";
        string day = "Monday";

        // String interpolation reads better than a chain of + operators.
        string greeting = $"Hello {name}. Today is {day}.";
        Console.WriteLine(greeting);
        // => Hello Alex. Today is Monday.
        // </Interpolation>
    }

    private static void UseConcatAndJoin()
    {
        // <ConcatJoin>
        string[] words = ["The", "quick", "brown", "fox"];

        // Concat joins the sequence with no separator.
        string runTogether = string.Concat(words);
        Console.WriteLine(runTogether);
        // => Thequickbrownfox

        // Join places a separator between each element.
        string sentence = string.Join(' ', words);
        Console.WriteLine(sentence);
        // => The quick brown fox
        // </ConcatJoin>
    }

    private static void UseStringBuilder()
    {
        // <StringBuilder>
        // StringBuilder builds a string in place, which suits loops
        // that append many pieces.
        var builder = new StringBuilder();
        for (int i = 1; i <= 3; i++)
        {
            builder.AppendLine($"Line {i}");
        }

        Console.Write(builder.ToString());
        // => Line 1
        // => Line 2
        // => Line 3
        // </StringBuilder>
    }
}

string.Join is the right tool whenever you need delimited output, such as comma-separated values or space-separated words.

Build a string in a loop

Each + or += operation creates a new string, because strings are immutable. When you append many pieces in a loop, that allocation adds up. The System.Text.StringBuilder class builds the result in a single buffer instead:

sample · csharpdocs/csharp/fundamentals/strings/common-tasks/snippets/concatenate/Program.csStringBuilder

csharp
using System.Text;

namespace ConcatenateStrings;

public static class Program
{
    public static void Main()
    {
        CombineLiterals();
        Console.WriteLine();
        UseOperators();
        Console.WriteLine();
        UseInterpolation();
        Console.WriteLine();
        UseConcatAndJoin();
        Console.WriteLine();
        UseStringBuilder();
    }

    private static void CombineLiterals()
    {
        // <Literals>
        // The compiler joins adjacent string literals at compile time,
        // so splitting a long literal across lines has no run-time cost.
        string message =
            "This is the first sentence of a longer message. " +
            "This is the second sentence. " +
            "This is the third and final sentence.";

        Console.WriteLine(message);
        // => This is the first sentence of a longer message. This is the second sentence. This is the third and final sentence.
        // </Literals>
    }

    private static void UseOperators()
    {
        // <Operators>
        string name = "Alex";
        string day = "Monday";

        // Use + to build a string from variables and literals.
        string greeting = "Hello " + name + ". Today is " + day + ".";
        Console.WriteLine(greeting);
        // => Hello Alex. Today is Monday.

        // Use += to append to an existing string.
        greeting += " How are you today?";
        Console.WriteLine(greeting);
        // => Hello Alex. Today is Monday. How are you today?
        // </Operators>
    }

    private static void UseInterpolation()
    {
        // <Interpolation>
        string name = "Alex";
        string day = "Monday";

        // String interpolation reads better than a chain of + operators.
        string greeting = $"Hello {name}. Today is {day}.";
        Console.WriteLine(greeting);
        // => Hello Alex. Today is Monday.
        // </Interpolation>
    }

    private static void UseConcatAndJoin()
    {
        // <ConcatJoin>
        string[] words = ["The", "quick", "brown", "fox"];

        // Concat joins the sequence with no separator.
        string runTogether = string.Concat(words);
        Console.WriteLine(runTogether);
        // => Thequickbrownfox

        // Join places a separator between each element.
        string sentence = string.Join(' ', words);
        Console.WriteLine(sentence);
        // => The quick brown fox
        // </ConcatJoin>
    }

    private static void UseStringBuilder()
    {
        // <StringBuilder>
        // StringBuilder builds a string in place, which suits loops
        // that append many pieces.
        var builder = new StringBuilder();
        for (int i = 1; i <= 3; i++)
        {
            builder.AppendLine($"Line {i}");
        }

        Console.Write(builder.ToString());
        // => Line 1
        // => Line 2
        // => Line 3
        // </StringBuilder>
    }
}

Reach for StringBuilder when the number of pieces is large or unknown at compile time. For a fixed, small set of values, the + operator and string interpolation are clearer. For guidance on when each approach performs best, see The string and StringBuilder types.

See also