string.Format in C# — syntax, format specifiers, and examples
string.Format composes a string by replacing numbered placeholders ({0}, {1}, …) with supplied values. It has been superseded by string interpolation in most scenarios, but it remains the right choice when the format string is stored externally (config file, resource file, database) or when building reusable message templates.
Every Console.WriteLine call that accepts a format string uses the same composite formatting rules internally.
Basic Syntax
C# Example Code
// {index} — positional placeholder
string result = string.Format("Hello, {0}! You have {1} messages.", "Alice", 5);
Console.WriteLine(result);
// Hello, Alice! You have 5 messages.
// Reuse the same argument multiple times
string repeated = string.Format("{0} + {0} = {1}", 7, 14);
Console.WriteLine(repeated);
// 7 + 7 = 14
// Pass a params array
object[] args = { "Bob", 42 };
Console.WriteLine(string.Format("Name: {0}, Age: {1}", args));
// Name: Bob, Age: 42Numeric Format Specifiers
C# Example Code
double amount = 12345.6789;
int count = 42;
double ratio = 0.1875;
int hex = 255;
// C — currency (uses current culture)
Console.WriteLine(string.Format("{0:C}", amount)); // $12,345.68
Console.WriteLine(string.Format("{0:C0}", amount)); // $12,346 (0 decimal places)
// D — decimal integer (integer types only)
Console.WriteLine(string.Format("{0:D}", count)); // 42
Console.WriteLine(string.Format("{0:D6}", count)); // 000042 (zero-padded to 6 digits)
// F — fixed-point
Console.WriteLine(string.Format("{0:F}", amount)); // 12345.68
Console.WriteLine(string.Format("{0:F4}", amount)); // 12345.6789 (4 decimal places)
// N — number with thousands separator
Console.WriteLine(string.Format("{0:N}", amount)); // 12,345.68
Console.WriteLine(string.Format("{0:N0}", amount)); // 12,346 (no decimal places)
// P — percentage
Console.WriteLine(string.Format("{0:P}", ratio)); // 18.75 %
Console.WriteLine(string.Format("{0:P1}", ratio)); // 18.8 %
// X — hexadecimal
Console.WriteLine(string.Format("{0:X}", hex)); // FF
Console.WriteLine(string.Format("{0:X4}", hex)); // 00FF (padded to 4 hex digits)
// E — scientific notation
Console.WriteLine(string.Format("{0:E}", amount)); // 1.234568E+004
Console.WriteLine(string.Format("{0:E2}", amount)); // 1.23E+004Alignment and Column Padding
A format item can include an alignment component: {index,width:format}. Positive width right-aligns; negative width left-aligns.
C# Example Code
// Right-align numbers in a column of width 10
Console.WriteLine(string.Format("{0,10}", "Amount"));
Console.WriteLine(string.Format("{0,10:C}", 9.99));
Console.WriteLine(string.Format("{0,10:C}", 1234.50));
Console.WriteLine(string.Format("{0,10:C}", 99999.00));
// Output:
// Amount
// $9.99
// $1,234.50
// $99,999.00
// Left-align strings, right-align numbers — tabular report
var items = new[]
{
("Keyboard", 49.99m),
("Monitor", 299.00m),
("Mouse", 24.95m)
};
Console.WriteLine(string.Format("{0,-15} {1,10}", "Product", "Price"));
Console.WriteLine(new string('-', 26));
foreach (var (name, price) in items)
Console.WriteLine(string.Format("{0,-15} {1,10:C}", name, price));
// Output:
// Product Price
// --------------------------
// Keyboard $49.99
// Monitor $299.00
// Mouse $24.95Date and Time Formatting
C# Example Code
DateTime dt = new DateTime(2025, 6, 15, 14, 30, 0);
Console.WriteLine(string.Format("{0:d}", dt)); // 6/15/2025 (short date)
Console.WriteLine(string.Format("{0:D}", dt)); // Sunday, June 15, 2025
Console.WriteLine(string.Format("{0:t}", dt)); // 2:30 PM (short time)
Console.WriteLine(string.Format("{0:T}", dt)); // 2:30:00 PM (long time)
Console.WriteLine(string.Format("{0:f}", dt)); // Sunday, June 15, 2025 2:30 PM
Console.WriteLine(string.Format("{0:g}", dt)); // 6/15/2025 2:30 PM
Console.WriteLine(string.Format("{0:s}", dt)); // 2025-06-15T14:30:00 (sortable ISO 8601)
Console.WriteLine(string.Format("{0:yyyy-MM-dd}", dt)); // 2025-06-15 (custom)Custom Numeric Format Strings
Use #, 0, and other picture characters for fully custom layouts.
C# Example Code
double value = 1234567.89;
// # — digit placeholder (suppresses leading/trailing zeros)
Console.WriteLine(string.Format("{0:#,#}", value)); // 1,234,568
Console.WriteLine(string.Format("{0:#,#.##}", value)); // 1,234,567.89
// 0 — digit placeholder (forces zeros)
Console.WriteLine(string.Format("{0:000.000}", 7.5)); // 007.500
// Phone number pattern
long phone = 4155551234;
Console.WriteLine(string.Format("{0:(###) ###-####}", phone)); // (415) 555-1234
// Positive / negative / zero sections
Console.WriteLine(string.Format("{0:+#;-#;zero}", 42)); // +42
Console.WriteLine(string.Format("{0:+#;-#;zero}", -7)); // -7
Console.WriteLine(string.Format("{0:+#;-#;zero}", 0)); // zeroCulture-Aware Formatting
C# Example Code
using System.Globalization;
decimal price = 1234.56m;
var us = CultureInfo.GetCultureInfo("en-US");
var de = CultureInfo.GetCultureInfo("de-DE");
var jp = CultureInfo.GetCultureInfo("ja-JP");
Console.WriteLine(string.Format(us, "{0:C}", price)); // $1,234.56
Console.WriteLine(string.Format(de, "{0:C}", price)); // 1.234,56 €
Console.WriteLine(string.Format(jp, "{0:C}", price)); // ¥1,235string.Format vs String Interpolation
Both produce the same output. Choose based on your scenario.
C# Example Code
string name = "Alice";
decimal total = 249.99m;
// string.Format
string msg1 = string.Format("Hello, {0}! Your total is {1:C}.", name, total);
// String interpolation (C# 6+) — preferred for inline literals
string msg2 = $"Hello, {name}! Your total is {total:C}.";
// Both produce: "Hello, Alice! Your total is $249.99."| Scenario | Prefer |
|---|---|
| Inline, literal format string | String interpolation $"..." |
| Format string from a resource / config | string.Format |
| Localized UI messages | string.Format with IFormatProvider |
| Logging frameworks (structured logging) | Message templates ({PropertyName}) |
| Building report columns with alignment | string.Format with ,width |