ToString. This C# method 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. We test the performance of ToString with various arguments.
To start, the ToString method is a virtual method on the object type. Every type inherits from object. Thus we can use an override ToString method to change the implementation used.
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);
}
}[1, 2]
Numbers. ToString is culture-sensitive. For a Double whose value is zero, the implementation of Double.ToString might return "0.00" or "0,00" depending on the UI culture.
Next We compare ToString() with no parameters (no format string) and ToString() with the NumberFormatInfo specified.
Info In many programs, there is no culture-sensitive code. I use ToString() in many places simply to convert an integer to a string.
Also ToString() with no parameters gets the culture internally, but this may be non-optimal.
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
Optimization. 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.
Thus ToString with no parameters gets a NumberFormatInfo. I have found that property accesses like get_CurrentCulture() are slow.
Info A solution to this inefficiency is to pass ToString() an already-created NumberFormatInfo.
using System;
using System.Globalization;
class Program
{
static void Main()
{
// This code converts the int 900 to a string.
string a = 900.ToString();
Console.WriteLine(a);
// This code converts the int 900 to a string.// ... Has the same exact results.
NumberFormatInfo n = CultureInfo.InvariantCulture.NumberFormat;
string b = 900.ToString(n);
Console.WriteLine(b);
}
}900
900
Optimization, continued. Here is the ToString benchmark. We test the performance of NumberFormatInfo arguments to ToString in 2 tight loops.
Version 1 Here we call ToString with no arguments. The NumberFormatInfo is accessed internally in the ToString call.
Version 2 This code eliminates the need for ToString to access a property internally. This speeds up this operation in loops.
Result Version 2 is faster for invariant cultures. This optimization may be worth testing in certain loops.
using System;
using System.Diagnostics;
using System.Globalization;
class Program
{
const int _max = 1000000;
static void Main()
{
NumberFormatInfo f = CultureInfo.InvariantCulture.NumberFormat;
// Version 1: use ToString with no argument.
var s1 = Stopwatch.StartNew();
for (int i = 0; i < _max; i++)
{
string result = i.ToString();
if (result == null)
{
break;
}
}
s1.Stop();
// Version 2: use ToString with NumberFormatInfo argument.
var s2 = Stopwatch.StartNew();
for (int i = 0; i < _max; i++)
{
string result = i.ToString(f);
if (result == null)
{
break;
}
}
s2.Stop();
Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000000) / _max).ToString("0.00 ns"));
Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000000) / _max).ToString("0.00 ns"));
}
}104.68 ns ToString()
87.84 ns ToString(f)
A discussion. When using simple integers or other value types, consider specifying the invariant culture number format. This reduces the execution time.
Notes, lookup. We can implement a cache for string representations returned by ToString. Consider using a lookup table (array or Dictionary) and store already-created strings.
A summary. We used an override method for the ToString virtual method on the object type. We looked at some aspects of the ToString method on the int type in the C# language.
Dot Net Perls is a collection of tested code examples. Pages are continually updated to stay current, with code correctness a top priority.
Sam Allen is passionate about computer languages. In the past, his work has been recommended by Apple and Microsoft and he has studied computers at a selective university in the United States.
This page was last updated on Jul 23, 2021 (edit).