C# ToString Method

ToString is virtual. It returns a string representation. We must override ToString on custom types for the method to be effective. For numeric types, there are performance and functional differences with ToString.

Override. To start, the ToString method is a virtual method on the object type. Every type inherits from object. Thus you can use an override ToString method to change the implementation used.


Then: When the ToString method is called on the instance, the override method is used. Here we override the ToString method.

C# program that overrides ToString

using System;

class Perl
    int _a;
    int _b;

    public Perl(int a, int b)
	_a = a;
	_b = b;

    public override string ToString()
	return string.Format("[{0}, {1}]", _a, _b);

class Program
    static void Main()
	Perl perl = new Perl(1, 2);


[1, 2]

The ToString method on the Perl instance is never called directly. It is called inside Console.WriteLine. The Perl instance is received as an object, and the virtual method ToString is called internally.


Then: The override ToString specified above is invoked. This goes through the object reference.

Numbers. MSDN says ToString returns a human-readable string that is culture-sensitive. For an instance of the Double class whose value is zero, the implementation of Double.ToString might return "0.00" or "0,00" depending on the UI culture.

Next: Here we compare ToString() with no parameters (no format string) and ToString() with the NumberFormatInfo specified.

C# program that uses ToString

using System;
using System.Globalization; // Important

class Program
    static void Main()
	int a = 4000;
	int b = 654;
	double c = 453.4;
	double d = 50000.55555;

	string a1 = a.ToString();
	string a2 = a.ToString(NumberFormatInfo.InvariantInfo);
	Console.WriteLine(a1 + " " + a2);

	string b1 = b.ToString();
	string b2 = b.ToString(NumberFormatInfo.InvariantInfo);
	Console.WriteLine(b1 + " " + b2);

	string c1 = c.ToString();
	string c2 = c.ToString(NumberFormatInfo.InvariantInfo);
	Console.WriteLine(c1 + " " + c2);

	string d1 = d.ToString();
	string d2 = d.ToString(NumberFormatInfo.InvariantInfo);
	Console.WriteLine(d1 + " " + d2);



4000 4000
654 654
453.4 453.4
50000.55555 50000.55555

We see that the ToString() without a parameter (a1, b1, c1, d1) all return the same strings as the overloaded methods with a parameter. The word invariant means that the format doesn't vary with the social culture of the machine.


In many programs, there is no culture-sensitive code. I use ToString() in many places simply to convert an integer to a string. ToString() with no parameters gets the culture internally, but this may be non-optimal.

Internally, the ToString method on the int type uses a property called CultureInfo to get the current culture. It sends the System.IFormatProvider to the ToString method. So ToString with no parameters gets NumberFormatInfo on its own.

Intermediate LanguageInt

In my research, I have found that property accesses like get_CurrentCulture() above are slow. So, my solution to this inefficiency is to pass ToString() an already-created NumberFormatInfo. Here's how I changed the code.

Example that shows NumberFormat: C#

// A.
// This code converts the int 900 to a string.
string a = 900.ToString(); // "900"

// B.
// This code converts the int 900 to a string.
// Has the same exact results.
NumberFormatInfo n = CultureInfo.InvariantCulture.NumberFormat;
string b = 900.ToString(n); // "900"

Version B eliminates the need for ToString to access a property internally. This is a significant optimization for this operation, particularly in tight loops. It is around 10% faster for invariant cultures. Here we see the timings.

Benchmark results for ToString
    100000000 iterations tested.

i.ToString():                 14882 ms
i.ToString(NumberFormatInfo): 13931 ms [faster]

Code used in benchmark: C#

// Code used in tight loop:
string a = i.ToString();

// Code used outside of loop:
NumberFormatInfo f = CultureInfo.InvariantCulture.NumberFormat;

// Code used in second tight loop:
string a = i.ToString(f);

Discussion. Let's consider best practices when using the ToString method. When using simple integers or other value types, specify the invariant culture number format. This improves the relevant execution time by 10%.

Also: You can implement a cache for string representations returned by ToString, such as with a lookup table structure.

ToString Integer Optimization
Slow version of code: C#

string a = 5.ToString();

Fast version of code: C#

NumberFormatInfo n = CultureInfo.InvariantCulture.NumberFormat;
string a = 5.ToString(n);

Summary. We provided an example for using an override method for the ToString virtual method on the object type. Further, we looked at some aspects of the ToString method on the int type in the C# language.

Note: Inspecting intermediate language is an excellent way to develop best practices and rules for optimization.