String formatting is one of the most essential skills in C#. Whether youβre building APIs, reports, UI output, logs, or debugging tools, formatting text correctly makes your code clearer, faster to write, and easier to maintain.
This ultimate guide explains every major formatting technique, how it works, why it exists, and includes over 50 practical examples you can use immediately.
π₯ The Four Main Ways to Format Strings in C#
C# gives you several tools for formatting text. Each serves a different purpose:
- String Concatenation (
+)
Quick but messy – useful only for tiny one-offs. - Composite Formatting (
string.Format,Console.WriteLine("{0}", ...))
Uses numbered placeholders{0},{1}– older but still used in logging and localisation. - String Interpolation (
$"Hello {name}")
The modern standard – readable, powerful, uses braces{}to embed expressions. - Formatted Interpolation (
{value:format})
Interpolation with built-in format specifiers for numbers, dates, alignment, etc.
β 1. String Concatenation (+)
What it does
- Joins strings using the
+operator - The compiler converts the expression into calls to
string.Concat - Not recommended for long or dynamic output because of performance
Example
string name = "James";
string msg = "Hello " + name + ", welcome!";
Why use it
- Minimal syntax
- OK for small pieces of code or quick debugging
β 2. Composite Formatting (string.Format)
What it does
- Uses positional placeholders like
{0},{1} - Supports full format specifiers (
{0:C},{0:dd/MM/yyyy}) - Great for localisation because string layout can move positions without code changes
Example
string result = string.Format("Name: {0}, Age: {1}", "James", 58);
Why use it
- Useful in logging frameworks
- Good for apps needing localisation (UI strings from resources)
β 3. String Interpolation ($"...")
What it does
- Treats anything inside
{}as a C# expression - Replaces it with the resulting string
- Cleaner, safer, faster – preferred modern approach
Example
string msg = $"Hello {name}, you are {age} years old.";
Why use it
- Best readability
- Fewer mistakes
- Allows expressions directly inside
{}
β 4. Interpolated Format Strings ({value:format})
What it does
- Applies a format specifier to values inside an interpolated string
- Works for numbers, dates, currency, alignment, hex, percentages, and custom formats
Example
double price = 9.99;
string txt = $"Price: {price:C}";
Why use it
- Clean, powerful formatting
- Preferred for all production-quality output
π₯ Standard Numeric Format Strings
C# numeric formats are extremely powerful. You can control decimal places, currency, percentage, padding, hex, and more.
Hereβs what each specifier does:
N β Number format
Adds commas and thousands separators, applies decimal formatting.
double n = 12345.678;
$"{n:N}" // "12,345.68"
$"{n:N3}" // "12,345.678"
F β Fixed-point
Shows a fixed number of decimals (default = 2).
$"{n:F0}" // "12346"
$"{n:F3}" // "12345.678"
C β Currency
Uses your systemβs culture (Β£ for UK, $ for US, etc.).
double price = 19.5;
$"{price:C}" // Β£19.50 (UK)
E β Exponential/scientific notation
Useful for scientific programming.
double value = 1234;
$"{value:E2}" // "1.23E+003"
P β Percent
Multiplies by 100 and adds a percent sign.
double ratio = 0.125;
$"{ratio:P}" // "12.50 %"
$"{ratio:P0}" // "13%"
D β Decimal (integers only)
Pads numbers with zeros.
int id = 42;
$"{id:D6}" // "000042"
X β Hexadecimal
Useful in hardware programming, hashing, or bitwork.
int number = 255;
$"{number:X}" // "FF"
π₯ Custom Numeric Format Strings
0 β Zero placeholder
Shows digits; inserts zeros if missing.
double v = 5.2;
$"{v:000.00}" // "005.20"
# β Digit placeholder
Shows digits only if they exist.
double v = 5.2;
$"{v:###.##}" // "5.2"
, β Thousands separator
$"{1234567:#,##0}" // "1,234,567"
. β Decimal point
$"{123.456:#.00}" // "123.46"
% β Percentage
$"{0.75:#0%}" // "75%"
π₯ DateTime Formatting
C# supports both standard and custom date formats.
Standard formats
d β Short Date
DateTime dt = DateTime.Now;
$"{dt:d}" // "23/11/2025"
D β Long Date
$"{dt:D}" // "Sunday, 23 November 2025"
T β Long Time
$"{dt:T}" // "14:52:30"
o β Round-trip ISO 8601
Perfect for APIs and JSON.
$"{dt:o}" // "2025-11-23T14:52:30.0000000Z"
Custom formats
| Format | Meaning | Example |
|---|---|---|
yyyy | 4-digit year | 2025 |
MM | Month with leading zero | 03 |
dd | Day with leading zero | 07 |
HH | 24-hour | 16 |
mm | Minutes | 09 |
ss | Seconds | 42 |
Example:
$"{dt:yyyy-MM-dd HH:mm:ss}"
π₯ Alignment and Padding
Alignment in interpolation uses a comma:
$"{value,10}" // right-aligned in 10 chars
$"{value,-10}" // left-aligned
This is commonly used in console tables.
π₯ Escaping Braces {}
Because {} are formatting markers, escape them with double braces:
$"This prints a brace: {{ and }}"
π₯ Formatting Using IFormatProvider
You can force a different culture:
var fr = new CultureInfo("fr-FR");
$"{1234.56.ToString("N", fr)}" // "1 234,56"
π₯ Building Complex Strings (Advanced Techniques)
StringBuilder
Best for performance when generating large text.
var sb = new StringBuilder();
sb.AppendLine($"Name: {name}");
sb.AppendLine($"Age: {age}");
π₯ ToString Overloads on Custom Types
You can override ToString:
public override string ToString() => $"{FirstName} {LastName}";
Or support formatting:
π₯ String Formatting – Example Code:
π΅ Basic String Interpolation
String interpolation ($"...") is the cleanest and most modern way to build formatted strings.
1. Insert a variable
string name = "James";
$"Hello {name}";
β‘ Inserts the value directly into the string.
2. Insert expressions
$"2 + 2 = {2 + 2}";
β‘ Expressions are evaluated before formatting.
3. Call methods inline
$"Upper: {name.ToUpper()}";
β‘ Any valid C# expression can be used.
4. Inline conditional
$"Status: {(isActive ? "Active" : "Inactive")}";
β‘ Great for status messages.
5. Escape braces
$"Braces: {{hello}}";
β‘ Use {{ or }} to output { or }.
π΅ Numeric Standard Format Strings
These are built-in formats for numbers.
6. Number with commas
$"{12345.678:N}"
β‘ Adds thousands separators and 2 decimals.
7. Number with 3 decimals
$"{12345.678:N3}"
8. Fixed point
$"{123.456:F}"
β‘ Always shows 2 decimals.
9. No decimals
$"{123.456:F0}"
10. Currency
$"{9.99:C}"
β‘ Uses system locale.
11. Currency with US format
9.99.ToString("C", new CultureInfo("en-US"));
12. Percent
$"{0.123:P}"
β‘ Shows 12.30%.
13. Percent whole number
$"{0.123:P0}" // "12%"
14. Hex
$"{255:X}";
15. Decimal padded
$"{42:D5}" // "00042"
π΅ Custom Numeric Formats
These allow incredibly fine control.
16. Zero placeholder
$"{5.2:000.00}";
β‘ Pads missing digits with zeros.
17. Digit placeholder
$"{5.2:###.##}";
β‘ Only prints real digits.
18. Thousands separator
$"{1234567:#,##0}";
19. Force sign
$"{42:+#;-#;0}";
β‘ Output like +42 / -42.
20. Custom percent
$"{0.75:#0%}";
21. Custom suffix
$"{1000:#,##0 coins}";
22. Phone number formatting
$"{1234567890:(###) ###-####}";
π΅ Date and Time Formatting
23. Short date
$"{DateTime.Now:d}";
24. Long date
$"{DateTime.Now:D}";
25. Full date/time
$"{DateTime.Now:F}";
26. ISO 8601
$"{DateTime.Now:o}";
27. yyyy-MM-dd
$"{DateTime.Now:yyyy-MM-dd}";
28. HH:mm:ss
$"{DateTime.Now:HH:mm:ss}";
29. Combined custom
$"{DateTime.Now:ddd, dd MMM yyyy HH:mm}";
30. Month name
$"{DateTime.Now:MMMM}";
π΅ Alignment & Padding
Useful for console tables and formatted reports.
31. Right-align in 10 characters
$"{42,10}";
32. Left-align
$"{42,-10}";
33. Alignment with format
$"{1234,10:N0}";
34. Table header
$"{ "Name",-15 } { "Score",10 }";
35. Table row
$"{player,-15} {score,10}";
π΅ StringBuilder Formatting
36. AppendLine with interpolation
sb.AppendLine($"User: {name}");
37. Build a report
sb.AppendLine($"Total: {total:C}");
sb.AppendLine($"Date: {DateTime.Now:yyyy-MM-dd}");
π΅ Formatting Custom Types (ToString)
38. Override ToString
public override string ToString() => $"{First} {Last}";
39. Support custom formats
public string ToString(string format) =>
format switch
{
"L" => $"{Last}, {First}",
"F" => $"{First} {Last}",
_ => ToString()
};
40. Using the custom format
$"{person:F}";
π΅ 8. Culture-Specific Formatting
41. French
$"{1234.56.ToString("N", new CultureInfo("fr-FR"))}";
β‘ "1 234,56"
42. German
$"{1234.56.ToString("C", new CultureInfo("de-DE"))}";
β‘ "1.234,56 β¬"
π΅ Interpolated Verbatim Strings ($@"...")
Great for JSON, SQL, multi-line literals.
43. Multi-line JSON
string json = $@"
{{
""name"": ""{name}"",
""age"": {age}
}}";
44. Paths
string path = $@"C:\Users\{username}\Documents";
π΅ Logging & Diagnostics Formatting
45. Timestamp log
$"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] INFO: {msg}";
46. Warning log
$"[{DateTime.Now:T}] WARNING: {warning}";
47. Error log
$"[{DateTime.Now:o}] ERROR: {ex.Message}";
π΅ Miscellaneous Useful Formatting
48. Format booleans
$"{isReady ? "READY" : "WAIT"}";
49. Enum name
$"{status:G}";
50. Byte array β hex
BitConverter.ToString(bytes).Replace("-", "");
51. Ordinal suffix
$"{day}{(day % 10 == 1 ? "st" : day % 10 == 2 ? "nd" : day % 10 == 3 ? "rd" : "th")}";
52. Pad with characters
"Hello".PadLeft(10, '*');
53. Accounting negatives
$"{-1234:#,##0;(#,##0);0}";
54. File size formatter
$"{bytes / 1024.0:N2} KB";
55. TimeSpan
$"{ts:hh\\:mm\\:ss}";