Home
C#
ToString: Get String From Object
This page was last reviewed on Jul 23, 2021.
Dot Net Perls
ToString. This C# method is virtual. It returns a string representation. We must override ToString on custom types for the method to be effective.
Shows a method
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.WriteLine
Shows a method
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.
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.
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.
Intermediate Language
int
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.
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.
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).
Home
Changes
© 2007-2024 Sam Allen.