Everything you need to know about ToString method

Name: *
My email: *
Recipient email: *
Message: *
Fields marked as bold are compulsory.
You haven't filled in compulsory values. The email is not correct

ToString method is one of the mostly used methods of the .Net framework. It's hard to find a developer who has never heard of it. Data is stored and processed through many different objects. It is highly possible however, there will come a time when you will want to present results to another human. This is where ToString comes in play. ToString, simply to say, will return a string value containing an object the way it is best comprehended by a human being. A numeric value object will be represented as a fair number, a DateTime as an easy-to-read date and so on. Despite of the default way this method will form a value, we can create our own representations.
 

Getting Started

ToString is a virtual method contained within the object class. Object is .Net's base class. As told, everything is an object. Since everything is an object, everything inherits its methods, and everything has a ToString method.
 
So what is this method actually doing? The following examples will give you an idea.
 
(3.14).ToString()                        --> "3.14"
(3.141).ToString("F2")                 --> "3.14"
(1000.1).ToString("C")                --> "1.000,10 €"

(DateTime.Now).ToString("d")     --> "31/1/2013"

You don't have to worry about what the exact meaning of these statements is. What is important so far, is to realize that all this method does is to return a string representing the object. No matter if this is a double or a DateTime object or any other object.

 
A string representation of an object is mostly used to create text that a person can read. For example, using
 
The time is: <asp:Label runat="server" ID="OutputLbl" />
 
and code behind
 
        string now = (DateTime.Now).ToString("HH:mm:ss");
 
        OutputLbl.Text = now; 
 
we get 
 
The time is: 23:30:36
 
 

A second look

Let's take a look at the numerous ways you can use this method using C#. To create different aspects of the ToString method we will use a single output named OutputLbl . 
 
To begin with, we create a simple example. Let's use ToString on a simple object.
 
    private void ObjectToString()
    {
        string tostring = "object.ToString() --> ";
 
        object randomObject = new object();
        string output = randomObject.ToString();
 
        OutputLbl.Text = tostring + output;
    }
 
The output will be 
 
object.ToString --> System.Object.
 
 
Now, we will try out ToString on an array of integers.
 
 private void ArrayToString()
    {
        string tostring = "intArray.ToString() --> ";
        
        int[] intArray = {0,1,2};
        string output = intArray.ToString();
 
        OutputLbl.Text = tostring + output;
    }
 
In contrast to the first example the output will be
 
intArray.ToString() --> System.Int32[]
 
as ToString has no ability to print our array in the form of "0,1,2" as we might have expected.
 
Can we handle this ourselves? As mentioned earlier, ToString is a virtual method of the class object. So, we can simply override it. We'll do just that, in order to create a ToString method that will print the contents of an array of integers. To do this we will have to create the intArrayClass class which will override the object class ToString method. Here's the code:
 
class intArrayClass
{
    int[] intArray;
 
    public intArrayClass(int[] integerArray)
    {
        intArray = integerArray;
    }
 
    public override string ToString()
    {
        string returnString = "";
 
        //Add each integer to the string seperated by commas
        foreach (int arrayElement in intArray)
            returnString += arrayElement.ToString() + ",";
 
        //Remove last comma
        if (returnString.Length > 0)
                returnString = returnString.Remove(returnString.Length - 1);
 
        return returnString;
    }
}
 
That's all we need. Now let's give it another try.
    private void ArrayToStringOverride()
    {
        string tostring = "intArrayClass.ToString() --> ";
 
        int[] intArray = { 0, 1, 2 };
        //Create the new class object
        intArrayClass arrayClass = new intArrayClass(intArray);
        string output = arrayClass.ToString();
 
        OutputLbl.Text = tostring + output;
    }
 
This time, the output will be 
intArrayClass.ToString() --> 0,1,2
 
 

Numeric format strings

OK, so far we’ve seen how you can create your own ToString methods. However you will not need to do this very often as .Net has already created many aspects to create strings from most common objects. Let’s see how.

 
A ToString method can get be the target of many arguments. These are called format strings. Depending on the format string the output will show a different view of the object.
 

To begin with we'll go through the strings that can be the output of a numeric value. We’ll make a start using simple decimal numbers.

 
Using "D" ("d") the output will be a simple string representation of an integer. Adding the number of digits next to the character will fill all remaining digits with zeros.
 
 private void DecimalToString()
    {
        //Decimals
        //Standard decimal output
        string outputString = " 314.ToString(D) --> ";
        outputString += 314.ToString("D") + "<br/>";
        //Standard decimal output with digits
        outputString += " 314.ToString(d4) --> ";
        outputString += 314.ToString("d4") + "<br/>";
 
        OutputLbl.Text = outputString;
    }
 
314.ToString(D) --> 314
314.ToString(d4) --> 0314
 
Using "F" ("f") you can create fixed point output. The number of digits next to the character is the number of decimal digits in this case as well.  You can also use localization attribute (using the System.Globalization libray) to show the number according to local settings.
 
    private void FixedPointToString()
    {
 
        double randomDouble = Math.PI * 1000;
 
        //Fixed Point
        //Standard numeric output
        string outputString = " 1000π.ToString(F) --> ";
        outputString += randomDouble.ToString("F") + "<br/>";
        //Numeric output with digits
        outputString += " 1000π.ToString(F4) --> ";
        outputString += randomDouble.ToString("F4") + "<br/>";
        //Numeric output with digits and localization
        outputString += " 1000π.ToString(f4,en-US) --> ";
        outputString += randomDouble.ToString("f4", CultureInfo.GetCultureInfo("en-US")) + "<br/>";
 
        OutputLbl.Text = outputString;
    }
 
1000π.ToString(F) --> 3141,59
1000π.ToString(F4) --> 3141,5927
1000π.ToString(f4,en-US) --> 3141.5927
 
Using "N" ("n"), is about the same thing as using fixed point format strings. In addition, you can have a decimal separator according to local settings.
 
    private void NumberToString()
    {
        double randomDouble = Math.PI * 1000;
 
        //Number
        string outputString = " 1000π.ToString(n4,en-US) --> ";
        outputString += randomDouble.ToString("n4", CultureInfo.GetCultureInfo("en-US")) + "<br/>";
 
        OutputLbl.Text = outputString;
    }
 
1000π.ToString(n4,en-US) --> 3,141.5927
 
"G" ("g") can be used as a number format string suitable to all numeric types.
Local settings and number of digits are present to most format strings, so from now on we will not pay extra attention to them and use en-US setings instead. 
 
Using "E"  ("e") you can create exponential output.
    private void ExponentialToString()
    {
        double randomDouble = 123e-2;
 
        //Exponential
        string outputString = " 123e-2.ToString(e3,en-US) --> ";
        outputString += randomDouble.ToString("e3", CultureInfo.GetCultureInfo("en-US"));
 
        OutputLbl.Text = outputString;
    }
 
123e-2.ToString(g4,en-US) --> 1.230e+000
 
The "X"  ("x") identifier will create a hexadecimal output.
    private void HexadecimalToString()
    {
        int randomInt = 523;
 
        //Exponential
        string outputString = " 523.ToString(g4,en-US) --> ";
        outputString += randomInt.ToString("x", CultureInfo.GetCultureInfo("en-US"));
 
        OutputLbl.Text = outputString;
    }
 
523.ToString(x,en-US) --> 20b
 
* Keep in mind that a type of number not supported by format strings will result in raising a Format Exception!
 
 
Using "P" ("p") you get the percentage output. For example:
    private void PercentageToString()
    {
        double randomDouble = 0.5231;
 
        //percentage
        string outputString = " 0.5231.ToString(x,en-US) --> ";
        outputString += randomDouble.ToString("p1", CultureInfo.GetCultureInfo("en-US"));
 
        OutputLbl.Text = outputString;
    }
 
0.5231.ToString(p,en-US) --> 52.3 %
 
Last but not least, is the currency output, which is represented by "C" ("c"). Check it out.
    private void CurrencyToString()
    {
        double randomDouble = 52.31;
 
        //currency
        string outputString = " 52.31.ToString(c,en-US) --> ";
        outputString += randomDouble.ToString("c", CultureInfo.GetCultureInfo("en-US")) + "<br/>";
 
        outputString += " 52.31.ToString(c1,el-GR) --> ";
        outputString += randomDouble.ToString("c1", CultureInfo.GetCultureInfo("el-GR"));
 
        OutputLbl.Text = outputString;
    }
 
52.31.ToString(c,en-US) --> $52.31
52.31.ToString(c1,el-GR) --> 52,3 €
 

Custom numeric string formats

The string formats we've seen so far are called standard formats, because even though they seem to be flexible enough they do not truly allow the developer to show a number the way he really wants. In contrast, we can use the so called custom formats, where the output can become even more flexible, for instance adding text within the digits of the number. These custom formats can be used to any standard type they are fit, so it is not necessary for us to make a complete presentation of their application. 
 
For example
52.31.ToString(##.#) --> 52,3
52.31.ToString(##.000' tons') --> 52,310 tons
 
Most useful are the zero and digit characters. Consider them as a mask to create the output schema. For example ###.## is the format string that will print 3 digits above decimal place and two decimal digits if possible. On the contrary 000.00 would print the digits available and fill the rest with zeros. The example will make things clearer. 
 
    private void ZeroDigitCustomFormatString()
    {
        double randomDouble = 3.14;
 
        string outputString = " 3.14.ToString(#.#) --> ";
        outputString += randomDouble.ToString("#.#") + "<br/>";
 
        outputString += " 3.14.ToString(0.0) --> ";
        outputString += randomDouble.ToString("0.0") + "<br/>";
 
        outputString += " 3.14.ToString(##.###) --> ";
        outputString += randomDouble.ToString("##.###") + "<br/>";
 
        outputString += " 3.14.ToString(00.000,en-US) --> ";
        outputString += randomDouble.ToString("00.000", CultureInfo.GetCultureInfo("en-US"));
 
        OutputLbl.Text = outputString;
    }
 
3.14.ToString(#.#) --> 3,1
3.14.ToString(0.0) --> 3,1
3.14.ToString(##.###) --> 3,14
3.14.ToString(00.000,en-US) --> 03.140
 
 
As you may have already noticed, the decimal point ('.') is used to determine where the decimal separator is to be placed.
 
A similar separator is the comma separator. It can be used as a group separator . For example
    private void CommaCustomFormatString()
    {
        double randomDouble = 1233;
 
        //comma seperator
        string outputString = " 1233.ToString(#,#,en-US) --> ";
        outputString += randomDouble.ToString("#,#", CultureInfo.GetCultureInfo("en-US")); 
 
 
        OutputLbl.Text = outputString;
    }
 
1233.ToString(#,#,en-US) --> 1,233
 
You can easily insert text within your format string.
    private void TextCustomFormatString()
    {
        double randomDouble = 123.3;
 
        //Insert text
        string outputString = " 123.3.ToString(#.#,) --> ";
        outputString += randomDouble.ToString("#.# km/h" );
 
 
        OutputLbl.Text = outputString;
    }
 
123.3.ToString(#.# km/h) --> 123,3 km/h
 
The last two custom format string characters are similar. They are the percentage and the exponential characters.
Using some of the previous options to create an interesting example we get
 
    private void PercentExponentialCustomFormatString()
    {
        double randomDouble = 123.3e-3;
 
        //Percentage custom string
        string outputString = " 123.3e-3.ToString(00.#%) --> ";
        outputString += randomDouble.ToString("00.#%") + "<br/>";
 
        //exponential custom string
        outputString += " 123.3e-3.ToString(0.##e+00) --> ";
        outputString += randomDouble.ToString("0.##e+00");
 
 
        OutputLbl.Text = outputString;
    }
 
123.3e-3.ToString(00.#%) --> 12,3%
123.3e-3.ToString(0.##e+00) --> 1,23e-01
 
There are still, a few more tricks which I think are quite uncommon to use. You can however search them up if you wish.
 
 

Date and time string formats

Before we are done with this article we should take a look at the DateTime string formats. They are quite common to come across. Since I bet most of you would not be comfortable with Greek dates such as Τετάρτη, 6 Φεβρουαρίου 2013, I will use en-US as my default local culture info.
 
There are quite a few DateTime string formats and it would be a bit difficult for me to explain what their output would be, so I will print the outputs instead. This will make things much easier to comprehend.
 
  private void DateTimeFormatString()
    {
        DateTime now = DateTime.Now;
 
        string outputString = " now.ToString(d) --> ";
        outputString += now.ToString("d", CultureInfo.GetCultureInfo("en-US")) + "<br/>";
 
        outputString += " now.ToString(D) --> ";
        outputString += now.ToString("D", CultureInfo.GetCultureInfo("en-US")) + "<br/>";
 
        outputString += " now.ToString(f) --> ";
        outputString += now.ToString("f", CultureInfo.GetCultureInfo("en-US")) + "<br/>";
 
        outputString += " now.ToString(F) --> ";
        outputString += now.ToString("F", CultureInfo.GetCultureInfo("en-US")) + "<br/>";
 
        outputString += " now.ToString(g) --> ";
        outputString += now.ToString("g", CultureInfo.GetCultureInfo("en-US")) + "<br/>";
 
        outputString += " now.ToString(G) --> ";
        outputString += now.ToString("G", CultureInfo.GetCultureInfo("en-US")) + "<br/>";
 
        outputString += " now.ToString(M) (equals to m) --> ";
        outputString += now.ToString("M", CultureInfo.GetCultureInfo("en-US")) + "<br/>";
 
        outputString += " now.ToString(O) (equals to o)--> ";
        outputString += now.ToString("O", CultureInfo.GetCultureInfo("en-US")) + "<br/>";
 
        outputString += " now.ToString(R) (equals to r)--> ";
        outputString += now.ToString("R", CultureInfo.GetCultureInfo("en-US")) + "<br/>";
 
        outputString += " now.ToString(s) --> ";
        outputString += now.ToString("s", CultureInfo.GetCultureInfo("en-US")) + "<br/>";
 
        outputString += " now.ToString(t)--> ";
        outputString += now.ToString("t", CultureInfo.GetCultureInfo("en-US")) + "<br/>";
 
        outputString += " now.ToString(T) --> ";
        outputString += now.ToString("T", CultureInfo.GetCultureInfo("en-US")) + "<br/>";
 
        outputString += " now.ToString(u) --> ";
        outputString += now.ToString("u", CultureInfo.GetCultureInfo("en-US")) + "<br/>";
 
        outputString += " now.ToString(U)--> ";
        outputString += now.ToString("U", CultureInfo.GetCultureInfo("en-US")) + "<br/>";
 
        outputString += " now.ToString(Y) (equals to y)--> ";
        outputString += now.ToString("Y", CultureInfo.GetCultureInfo("en-US"));
 
        OutputLbl.Text = outputString;
    }
 
now.ToString(d) --> 2/6/2013
now.ToString(D) --> Wednesday, February 06, 2013
now.ToString(f) --> Wednesday, February 06, 2013 9:23 PM
now.ToString(F) --> Wednesday, February 06, 2013 9:23:51 PM
now.ToString(g) --> 2/6/2013 9:23 PM
now.ToString(G) --> 2/6/2013 9:23:51 PM
now.ToString(M) (equals to m) --> February 06
now.ToString(O) (equals to o)--> 2013-02-06T21:23:51.2165809+02:00
now.ToString(R) (equals to r)--> Wed, 06 Feb 2013 21:23:51 GMT
now.ToString(s) --> 2013-02-06T21:23:51
now.ToString(t)--> 9:23 PM
now.ToString(T) --> 9:23:51 PM
now.ToString(u) --> 2013-02-06 21:23:51Z
now.ToString(U)--> Wednesday, February 06, 2013 7:23:51 PM
now.ToString(Y) (equals to y)--> February, 2013
 
Now, let's take a look at the points of interest.
  • Whenever there are both, a capital and a lower-case string format of the same character (which cause a different output), the capital will show extended info of the same type.
  •  D refers to date output.
  •  F refers to full date and time output.
  •  M refers to month and date output
  •  T refers to time output
  •  Y refers to year and month output.
 

Custom date and time string formats

If none of the previous options is to your liking, you can create your own output. There are custom string formats you can use. The following example will make things much clearer.
 
    private void DateTimeCustomFormatString()
    {
        //Basic date and time custom format applications
 
        DateTime now = DateTime.Now;
 
        string outputString = " now.ToString(o) --> ";
        outputString += now.ToString("o") + "<br/>";
 
        outputString += " now.ToString(MM/dd/yy) --> ";
        outputString += now.ToString("MM/dd/yy") +"<br/>";
 
        outputString += " now.ToString(ddd MMM d, yyyy, en-US) --> ";
        outputString += now.ToString("ddd MMM d, yyyy", CultureInfo.GetCultureInfo("en-US")) + "<br/>";
 
        outputString += " now.ToString(dddd MMMM d, yyyy, en-US) --> ";
        outputString += now.ToString("dddd MMMM d, yyyy", CultureInfo.GetCultureInfo("en-US")) + "<br/>";
 
        outputString += " now.ToString(h:mm:s:f) --> ";
        outputString += now.ToString("h:m:s:f") +"<br/>";
 
        outputString += " now.ToString(hh:mm:ss tt, en-US) --> ";
        outputString += now.ToString("hh:mm:ss tt", CultureInfo.GetCultureInfo("en-US")) + "<br/>";
 
        outputString += " now.ToString(HH:mm:ss:FF) --> ";
        outputString += now.ToString("HH:mm:ss:FF") + "<br/>";
 
        outputString += " now.ToString('The time is ' hh:mm:ss tt,  en-US) --> ";
        outputString += now.ToString("'The time is ' hh:mm tt", CultureInfo.GetCultureInfo("en-US")) + "<br/>";
 
 
        OutputLbl.Text = outputString;
    }
 
 
now.ToString(o) --> 2013-02-06T22:07:16.2125781+02:00
now.ToString(MM/dd/yy) --> 02/06/13
now.ToString(ddd MMM d, yyyy, en-US) --> Wed Feb 6, 2013
now.ToString(dddd MMMM d, yyyy, en-US) --> Wednesday February 6, 2013
now.ToString(h:mm:s:f) --> 10:7:16:2
now.ToString(hh:mm:ss tt, en-US) --> 10:07:16 PM
now.ToString(HH:mm:ss:FF) --> 22:07:16:21
now.ToString('The time is ' hh:mm tt, en-US) --> The time is 10:07 PM

 

 

Let's take a look at some points of interest concerning date and time custom string formats.
  • h -> hours, m -> minutes, s -> seconds, f->tenths of seconds
  • y -> years, M -> months, d -> days
  • In most cases we can choose between one and two of the same characters aligned. This will result in showing the output using one or two digits (eg m -> 6, mm -> 06)
  • h will  show the hours using a twelve-hour clock. HH will use a 24-hour clock.
  •  tt will result in AM or PM
  • You can insert a string the way the last line of the example does.
 

Conclusion

It is important to know how to effectively use the ToString method. There are a lot of standard ways you can represent a numeric value. If however none of them is good enough for you, you can create your own custom ones. Similar representations exist for date and time values. If you master full understanding of the ToString method it is quite unlikely that you will find yourself in a position where you cannot create the desired output. 

 

 

Back to BlogPreviousNext

Comments


  • 13-10-2013, 14:08 PM
    kbadas
    Posts: 6
    Indeed. ToString() should be primarily used to create nice output. Not to create strings within the source code, since as you stated things might get tricky. Errors may show up when using dictionary keys or string comparison generally. Keeping that in mind, you should use ToString() only when you are sure that it will have no unexpected effect at runtime.
  • 10-10-2013, 18:36 PM
    Stefanos
    Posts: 1
    One thing to keep in mind is that ToString() may return a different value depending on culture/locale of the underlying system. This means that it should not be used as a dictionary key. Override and use GetHashCode() instead (it is usually a good idea to override GetHashCode() if you override ToString() and vice versa.)

Leave a comment
Name: