Starbeamrainbowlabs

Stardust
Blog

C♯'s String.Format: A (hopefully) complete tutorial

For a while now whenever I've been formatting strings I've been using the String.Format() method that's built into C♯. Recently, I found it's documentation page, and found that I didn't know the half of what it was capable of, so I decided to learn all of it's tricks and write a tutorial for this blog at the same time. Firstly, here's an example of it in action:

int number = 4626;
string textLine = String.Format("The number is {0}", number);
Console.WriteLine(textLine);

You can pass a number of variables in after the string's format, and they can be referenced in the string itself through the curly braces syntax: {0}. 0 refers to the first variable, {1} to the second, etc. Anything you pass in will have it's .ToString() method called, so you can control how your classes are represented.

We can go one better than the above though. The Console.Write() and Console.WriteLine() methods have String.Format() functionality built in, so we can shorten the above down to 2 lines:

int number = 4626;
Console.WriteLine("The number is {0}", number);

Logging a table of data to the console? You can also pad any variable to make it a given length. Just add a comma and then the length that you want it to pad shorter strings to:

Random rng = new Random();
for(int i = 0; i < 100; i++)
{
    Console.WriteLine("{0,4}: {1}", i, rng.Next());
}

The above will output something similar to this:

   0: 1386044068
   1: 337840762
   2: 796579848
   3: 2124870500
   4: 1451010095
   5: 2086322183
   6: 2057125438
   7: 1856321748
   8: 1688522403
   9: 982979897
  10: 1571218679
  11: 1851393877
  12: 572762676
  13: 549024616
  14: 1496101994
...

By default, it pushes things to the right, but you can make it do the opposite by adding a minus sign to the padding length. So if you wanted to push the first variable to the left and have a minimum length of 4, it would be {0,-4}.

It doesn't stop there though. For numbers, you can convert can control the number of decimal places that are displayed. This is done like this:

Random rng = new Random();
for(int i = 0; i < 100; i++)
{
    Console.WriteLine("{0,4}: {1:0.00}", i, rng.NextDouble());
}

Notice that we're using a colon instead of a comma here. The above will output something like this:

   0: 0.86
   1: 0.91
   2: 0.97
   3: 0.41
   4: 0.70
   5: 0.81
   6: 0.26
   7: 0.73
   8: 0.93
   9: 0.14
  10: 0.80
  11: 0.71
...

You can even automatically convert a number to a percentage by adding a percent sign (%), and it will automatically be multiplied by 100:

Random rng = new Random();
for(int i = 0; i < 100; i++)
{
    Console.WriteLine("{0,4}: {1:0.00%}", i, rng.NextDouble());
}

Then you get an output like this:

   0: 59.62%
   1: 37.75%
   2: 33.98%
   3: 44.40%
   4: 66.73%
   5: 83.00%
   6: 95.67%
   7: 47.98%
   8: 5.05%
   9: 88.48%

If you want to ensure that all the values have the same width (and who wouldn't?), you can combine the two syntaxes like this:

Random rng = new Random();
for(int i = 0; i < 100; i++)
{
    Console.WriteLine("{0,4}: {1,-8:0.00%}", i, rng.NextDouble());
}

The above produces something like this:

...
  12:   36.60%
  13:   60.48%
  14:   13.96%
  15:   36.88%
  16:    6.55%
  17:   89.51%
  18:   19.18%
  19:   91.98%
...

Numbers can also be converted to hex like this:

Random rng = new Random();
for(int i = 0; i < 100; i++)
{
    Console.WriteLine("{0,4}: {1:x8}", i, rng.Next());
}

The above formats the numbers as lowercase hex, and pads them to be at least 8 characters long. Here's what the above might output:

   0: 4d7867e8
   1: 3dc7d06d
   2: 118b1c4b
   3: 5cd477c5
   4: 580a74e1
   5: 69d50a4b
   6: 7ccf118e
   7: 25725808
   8: 093ddea4
   9: 164a7baf
...

Simply change the lowercase x to an uppercase one to change the format to be uppercase. Numbers aren't the only thing that String.Format() lets you play with though. Dates are supported too:

DateTime dt = DateTime.Now;
Console.WriteLine("Day {0:d} of the month of {0:m} the {0:yyyy}th year", dt);
// Output example: Day 04/09/2015 of the month of 04 September the 2015th year

That pretty much concludes this post about String.Format(). If I tried to demonstrate every little feature, we would be here all year! Before I go though, I have put together a quick reference guide on all the different formats that it supports:

Format Example Description
{0} cheese The first variable
{0,8} cheese Pad the first variable on the left to 8 characters
{0,-8} cheese Pad the first variable on the right to 8 characters
{0:0.00} 4.38 Round the first variable to 2 decimal places
{0,6:0.000} 3.432 Round the first variable to 3 decimal places and then pad it on the left to 6 characters
{0:x} efe9a Convert the first variable to lowercase hex
{0:X8} EFE9A Convert the first variable to uppercase hex and then pad it on the left to 8 characters.
{0:d} 06/09/2015 Extract the date part of a DateTime object.
{0:t} 02:19pm Extract the time part of a DateTime object
{0:hh} 02 Extract the hour from a DateTime object
{0:mm} 19 Extract the minute from a DateTime object
{0:ss} 56 Extract the seconds from a DateTime object

{0:dd} | 09 | Extract the day from a DateTime object {0:MM} | 09 | Extract the month from a DateTime object {0:M} | September | Extract the long month from a DateTime object {0:yy} | 15 | Extract the short year from a DateTime object {0:yyyy} | 2015 | Extract the long year from a DateTime object

Update 29th October 2015: A commenter by the name Tom let me know that in C♯ 6.0 and above (that's the .NET framework 4.6+) comes with another handy feature that lets you substitute in the contents of a variable directly. Here's his example:

int number = 4626;
Console.WriteLine("The number is {number}");

The above would output The number is 4626. This also extendes to properties of objects, letting you do something like this:

Console.WriteLine("Account {myAccount.Id} belongs to {myAccount.Name} and contains £{myAccount.Balance}.");

There's also a shorthand version of String.Format. Simply prefix a string with a dollar sign ($) and the string will be pushed through String.Format for you:

string display = $"Launch in T minus {rocket.Countdown} seconds!";
Console.WriteLine(display);

You can find out more here: New Language features of C# 6

Sources

Tag Cloud

3d 3d printing account algorithms android announcement architecture archives arduino artificial intelligence artix assembly async audio automation backups bash batch blender blog bookmarklet booting bug hunting c sharp c++ challenge chrome os cluster code codepen coding conundrums coding conundrums evolved command line compilers compiling compression conference conferences containerisation css dailyprogrammer data analysis debugging defining ai demystification distributed computing dns docker documentation downtime electronics email embedded systems encryption es6 features ethics event experiment external first impressions freeside future game github github gist gitlab graphics guide hardware hardware meetup holiday holidays html html5 html5 canvas infrastructure interfaces internet interoperability io.js jabber jam javascript js bin labs latex learning library linux lora low level lua maintenance manjaro minetest network networking nibriboard node.js open source operating systems optimisation outreach own your code pepperminty wiki performance phd photos php pixelbot portable privacy problem solving programming problems project projects prolog protocol protocols pseudo 3d python reddit redis reference release releases rendering research resource review rust searching secrets security series list server software sorting source code control statistics storage svg systemquery talks technical terminal textures thoughts three thing game three.js tool tutorial twitter ubuntu university update updates upgrade version control virtual reality virtualisation visual web website windows windows 10 worldeditadditions xmpp xslt

Archive

Art by Mythdael