When doing string concatenation in C#, why don't you have to call ToString on non string variables?

To get the string representation of a variable, in this case we’ll use int, there is no implicit conversion from int to string so you can call the ToString method:

string s = myInt; //INVALID!!
string s = myInt.ToString(); // Valid!

When concatenating with another string, though, you don’t have to do so:

string s = "First string " + myInt; //No ToString??!?

Why?

When performing string concatenation like above, the code is compiled to actually use the string.Concat(object, object) method. So our example above actually compiles to:

string s = string.Concat((object)"First string ", (object)myInt);

Notice the casts to object for both the string and int variables. This is also known as boxing:

Boxing is the process of converting a value type to the type object or to any interface type implemented by this value type. When the CLR boxes a value type, it wraps the value inside a System.Object and stores it on the managed heap. Unboxing extracts the value type from the object. Boxing is implicit; unboxing is explicit. The concept of boxing and unboxing underlies the C# unified view of the type system, in which a value of any type can be treated as an object.

The boxing and unboxing processes, as with anything, technically incur a performance penalty, but in the grand scheme of things they are nothing to worry about.

When it comes to string concatentation technically string s = "First string " + myInt.ToString(); is faster because it will use the string.Concat(string, string) overload. But the performance difference is so negligible that you should use whatever you find most readable.