A Guide to C# string.Format

A guide to the classic string.Format method in C#. Learn how to use this powerful method with indexed placeholders and format specifiers to create complex, formatted strings.

Before the introduction of string interpolation ($'') in C# 6, the standard and most powerful way to compose strings from variables was the static string.Format method. It provides a flexible and robust mechanism for creating formatted strings using indexed placeholders.

While string interpolation is now preferred for its superior readability, string.Format is still found in a vast amount of existing C# code and remains a useful tool in certain scenarios.

The Basic Syntax

string.Format works by taking a composite format string and a list of objects to format. The format string contains fixed text mixed with format items. A format item is an indexed placeholder, like {0} or {1}, that corresponds to one of the objects in the argument list.

string name = "Alice";
int age = 30;

// The {0} placeholder corresponds to 'name' (the first argument after the format string).
// The {1} placeholder corresponds to 'age' (the second argument).
string message = string.Format("My name is {0} and I am {1} years old.", name, age);

Console.WriteLine(message);
// Output: My name is Alice and I am 30 years old.

You can reuse the same index multiple times:

string message = string.Format("{0} is a great developer. I think {0} will do well.", name);

Format Specifiers

The real power of string.Format comes from format specifiers. You can add a colon : after the index to control how the value is formatted. This is especially useful for numbers, dates, and currency.

Formatting Numbers:

decimal price = 49.99m;

// 'C' is the currency format specifier
// It automatically uses the current culture's currency symbol and formatting.
string formattedPrice = string.Format("The price is {0:C}.", price);
// Output: The price is $49.99. (in a US culture setting)

// 'F2' formats as a fixed-point number with 2 decimal places.
string formattedNumber = string.Format("Value: {0:F2}", 123.4567);
// Output: Value: 123.46

Formatting Dates:

DateTime now = DateTime.Now;

// 'd' is the short date pattern
string shortDate = string.Format("Today is {0:d}.", now);
// Output: Today is 12/30/2020.

// 'D' is the long date pattern
string longDate = string.Format("Today is {0:D}.", now);
// Output: Today is Wednesday, December 30, 2020.

string.Format vs. String Interpolation

C# 6 introduced string interpolation, which provides a much more readable and concise syntax for the same functionality. The compiler actually translates string interpolation into string.Format calls behind the scenes.

string.Format:

string message = string.Format("Hello, {0}!", name);

String Interpolation:

string message = $"Hello, {name}!";

String interpolation is generally preferred because the variable is right there inside the string, making it much easier to read and less error-prone than matching indexes to an argument list.

When is string.Format Still Useful?

String interpolation is fantastic, but it only works when the format string is a compile-time constant. There are situations where your format string might come from a resource file, a database, or user configuration. In these cases, you cannot use string interpolation, and string.Format is the perfect tool for the job.

// Imagine this format string is loaded from a configuration file
string formatTemplate = "Welcome, {0}. You have {1} new messages.";

string message = string.Format(formatTemplate, userName, messageCount);

Conclusion

string.Format is a powerful and flexible method for building formatted strings in C#. While the more modern string interpolation syntax has replaced it for most day-to-day use cases due to its superior readability, string.Format remains an essential tool to understand. You will encounter it frequently in existing C# code, and it is still the go-to solution for scenarios where the format string is determined at runtime.