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