HomeSearch

C# ToString: Get String From Object

Override the virtual ToString method. Get a string representation with ToString.
ToString. This method is virtual. It returns a string representation. We must override ToString on custom types for the method to be effective.Strings
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.Object

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

Virtual

Info: The ToString method on the Perl instance is never called directly. It is called by the logic inside Console.WriteLine.

And: The Perl instance is received as an object, and the virtual method ToString is called internally.

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

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.

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); } } Output 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.

ILInt, uint

Info: A solution to this inefficiency is to pass ToString() an already-created NumberFormatInfo.

C# program that shows NumberFormat 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); } } Output 900 900
Optimization, continued. Here is the ToString benchmark. We test the performance of NumberFormatInfo arguments to ToString in 2 tight loops.Benchmark

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.

C# program that tests ToString performance 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")); } } Output 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.ToString Optimization
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.
© 2007-2020 Sam Allen. Every person is special and unique. Send bug reports to info@dotnetperls.com.
Home
Dot Net Perls