String concatenation and int indirect cast

Most programming languages provide the indirect conversions from numeric datatypes to string. So what difference it makes by calling the ToString() method when appending non-string datatypes to a string.

This article is divided into 2 parts. The first part will show how the ToString() is interpreted by the CLR when it is called on an integer. Using this understanding we then move to the second part of the article that compares the code generated during compilation when an integer is appended to a string using different techniques.

Understanding int.ToString()

To determine the effect of calling the int.ToString() we will compare the code generated when calling Console.WriteLine(int) and Console.WriteLine(int.ToString)

Test Scenario 1:

Let’s print an integer directly to the Console.

  1. int x = 10;
  2. Console.WriteLine(x);

The snippet above is compiled into the following instruction set.

  1. ldc.i4.s   10
  2. // Pushes the supplied int8 value onto the evaluation stack as an int32
  3. stloc.0  
  4. // Pops the current value from the top of the evaluation stack and stores it in the local variable list at index 0.
  5. ldloc.0
  6. // Loads the local variable at index 0 onto the evaluation stack.
  7. call       void [mscorlib]System.Console::WriteLine(int32)
  8. // Performs a function call to the static method Console.WriteLine(int32)

Note: The MSIL snippets in this article are generated using the Ildasm program provided with .NET by Microsoft.

In this case we notice that Console.Writeline() can handle integers directly so no conversions are being performed before the function call.

Test Scenario 2:

Now lets modify the code such that we use the ToString() method with the variable x.

  1. int x = 10;
  2. Console.WriteLine(x.ToString());

If we look again into the MSIL code generated by the compiler, a noticable difference is that the call to the method ToString() has resulted into a function call that is pushing the string representation of the numeric value on the stack. The result is then poped on the stack and read by WriteLine() methog call.

  1. ldloca.s   x
  2. // Loads the address of the local variable at a specific index onto the evaluation stack, short form
  3. call       instance string [mscorlib]System.Int32::ToString()
  4. // Calls the instance method ToString() on the previously pushed value on the evaluation stack.
  5. // The string returned by the function is pushed on the stack.
  6. call       void [mscorlib]System.Console::WriteLine(string)
  7. // Performs a function call to the static method Console.WriteLine(string)

From these two test scenarios one notices that the when the ToString() has been called a new string is being created on the stack which is then passed over to the enclosing function.

Article sections: