Should .ToString() Be Used When Concatenating String and Integer in C#?

c

int a = 1;
int b = 2;
int sum = a + b;
string expression = "Expression: " + a + " + " + b + " = " + sum;
Console.WriteLine(expression); //displays Expression 1 + 2 = 3

Should I use:

string expression = "Expression: " + a + " + " + b + " = " + sum;

or

string expression = "Expression: " + a.ToString() + " + " + b.ToString() + " = " + result.ToString();

Is it recommended to use ToString() when concatenating string and int?

Best Answer

ToString usage

No, you shouldn't use ToString here.

String concatenation automatically transforms non-strings into strings, which means that your two variants are nearly¹ identical:

When one or both operands are of type string, the predefined addition operators concatenate the string representation of the operands.

Source: C# Language Specification: Addition operator, MSDN.

On the other hand, the first one (without ToString):

  • Is shorter to write,
  • Is shorter to read,
  • Is easier to maintain and:
  • shows exactly the intention of the author: to concatenate strings.

So prefer the first one.

Under the hood

What is also interesting is to see what happens under the hood. One of the ways to see it is to watch the IL code within LINQPad. This program:

void Main()
{
    var a = 3;
    var b = " Hello";
    var c = a + b;
    Console.WriteLine(c);
}

is translated to the following IL:

IL_0001:  ldc.i4.3    
IL_0002:  stloc.0     // a
IL_0003:  ldstr       " Hello"
IL_0008:  stloc.1     // b
IL_0009:  ldloc.0     // a
IL_000A:  box         System.Int32
IL_000F:  ldloc.1     // b
IL_0010:  call        System.String.Concat
IL_0015:  stloc.2     // c
IL_0016:  ldloc.2     // c
IL_0017:  call        System.Console.WriteLine

See that System.String.Concat? That means that the original code can be written also like that, which translates into exactly same IL:

void Main()
{
    var a = 3;
    var b = " Hello";
    var c = string.Concat(a, b); // This is the line which was changed.
    Console.WriteLine(c);
}

When you read the documentation of string.Concat(object[]), you may learn that:

The method concatenates each object in args by calling the parameterless ToString method of that object; it does not add any delimiters.

This means that ToString is redundant. Also:

String.Empty is used in place of any null object in the array.

Which handles nicely the case where some of the operands are null (see the footnote 1).

While in the last example, concatenation was translated into string.Concat, one should also highlight compiler optimizations:

var a = "Hello " + "World";

is translated into:

ldstr       "Hello World"
stloc.0

On the other hand:

var a = string.Concat("Hello ", "World");

is translated into:

ldstr       "Hello "
ldstr       "World"
call        System.String.Concat
stloc.0

Other alternatives

There are of course other ways to concatenate string representations of objects in C#.

  1. StringBuilder is used when you need to do a lot of concatenation operations and helps reducing the number of intermediary strings created. Deciding whether you should use a StringBuilder or an ordinary concatenation may not be easy. Use a profiler or search for relevant answers on Stack Overflow.

    Using StringBuilder has a major drawback of making the code difficult to read and maintain. For simple cases as the one in your question, StringBuilder is not only harmful to the readability of the code, but also useless in terms of performance.

  2. string.Join should be used when you need to add delimiters.

    Obviously, never use string.Join with an empty delimiter to concatenate strings.

  3. string.Format can be used when string templating is preferred to string concatenation. One of the cases where you may prefer that is when the message may be localized, as suggested in the answer by kunthet.

    Using string.Format has several drawbacks which makes it unsuited for simple cases like yours:

    • With simple "{0}" placeholders, it is often unclear which parameter goes where. It is frequent to mistakenly reverse the parameters or to forget one. Luckily, C# 6 finally introduces string interpolation which solves this problem.

    • Runtime performance may degrade. Of course, don't assume string.Format is always slower. If performance matters, measure two approaches and determine which one is faster based on your actual results instead of assumptions.

    • The code is slightly longer to write, longer to read and harder to maintain, although this is extremely minor and shouldn't bother you too much.


¹ The difference appears when one of the objects is null. Without ToString, a null is replaced by an empty string. With ToString, a NullReferenceException is thrown.

Related Topic