A post of mine from 3 years ago about the performance differences between using string.Concat and the string class’s + operator got its first comment yesterday so I thought I’d flesh out what I said there to clarify what happens. First, here’s a little test program to show different ways to concatenate strings.
class Program { static void Main(string[] args) { Console.WriteLine("a" + "b" + "c" + "d"); Console.WriteLine(string.Concat("a", "b", "c", "d")); string a = "a"; string b = "b"; string c = "c"; string d = "d"; Console.WriteLine(string.Concat(a, b, c, d)); Console.WriteLine(a + b + c + d); } }
So now lets look at the IL generated from that, using our old friend Reflector.
.method private hidebysig static void Main(string[] args) cil managed { .entrypoint .maxstack 4 .locals init ( [0] string a, [1] string b, [2] string c, [3] string d) L_0000: nop L_0001: ldstr "abcd" L_0006: call void [mscorlib]System.Console::WriteLine(string) L_000b: nop L_000c: ldstr "a" L_0011: ldstr "b" L_0016: ldstr "c" L_001b: ldstr "d" L_0020: call string [mscorlib]System.String::Concat(string, string, string, string) L_0025: call void [mscorlib]System.Console::WriteLine(string) L_002a: nop L_002b: ldstr "a" L_0030: stloc.0 L_0031: ldstr "b" L_0036: stloc.1 L_0037: ldstr "c" L_003c: stloc.2 L_003d: ldstr "d" L_0042: stloc.3 L_0043: ldloc.0 L_0044: ldloc.1 L_0045: ldloc.2 L_0046: ldloc.3 L_0047: call string [mscorlib]System.String::Concat(string, string, string, string) L_004c: call void [mscorlib]System.Console::WriteLine(string) L_0051: nop L_0052: ldloc.0 L_0053: ldloc.1 L_0054: ldloc.2 L_0055: ldloc.3 L_0056: call string [mscorlib]System.String::Concat(string, string, string, string) L_005b: call void [mscorlib]System.Console::WriteLine(string) L_0060: nop L_0061: ret }
OK, so looking at the first method where we concatenate string literals using the + operator and we can see the compiler helps us out by concatenating the strings at compile time, which is going to be as optimal as possible. The second example shows that the compiler doesn’t do this magic when we use string.Concat so string.Concat is actually slower in this scenario.
Now if we look at the next examples where we concatenate string variables, the generated IL is exactly the same! So the performance characteristics are likely to be somewhat similar to say the least. Things get more interesting when you get beyond 4 strings since there is no version of string.Concat that takes more than 4 parameters, so they have to be pushed into an array but the result is the same, the + operator generates the exact same code as string.Concat.
So I can’t see a scenario where you’d want to use string.Concat (unless you’re particularly fond of it) and if string concatenation performance is an issue, you probably should be using the StringBuilder class.