C# ToString

String type

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

Virtual keyword

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.

Object

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

Virtual
Program that overrides ToString: C#

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);
	Console.WriteLine(perl);
    }
}

Output

[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.

Console.WriteLine

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

Numbers

Double keyword

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.

Program that uses ToString: C#

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);

    }
}

Output

4000 4000
654 654
453.4 453.4
50000.55555 50000.55555
Squares

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.

Overload

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.

Int

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 LanguageIntProperty

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"
Performance optimization

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
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

Programming tip

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

C# programming language

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.


C#: String