C# String Formatting
String formatting is an essential skill for any C# developer. It allows you to create well-structured, readable text output by combining strings with variables and controlling how they're displayed. Whether you're building console applications, web services, or desktop apps, effective string formatting will make your code more readable and your outputs more professional.
Introduction to String Formatting
In C#, there are several ways to format strings:
- String concatenation
- String interpolation
- Composite formatting with
string.Format()
StringBuilder
for complex string operations
Each approach has its advantages and ideal use cases, which we'll explore in this guide.
String Concatenation
The simplest way to combine strings is using the +
operator:
string firstName = "John";
string lastName = "Doe";
string fullName = firstName + " " + lastName;
Console.WriteLine(fullName); // Output: John Doe
While simple, concatenation becomes inefficient when combining many strings or when used in loops.
String Interpolation
Introduced in C# 6, string interpolation is a clean, readable way to embed variables directly within a string. You prefix the string with $
and place expressions within {}
:
string firstName = "John";
string lastName = "Doe";
int age = 30;
string message = $"Hello, my name is {firstName} {lastName} and I am {age} years old.";
Console.WriteLine(message);
// Output: Hello, my name is John Doe and I am 30 years old.
Formatting Numeric Values
You can format numbers within interpolated strings:
double price = 123.45;
Console.WriteLine($"Price: {price:C}"); // Output: Price: $123.45 (in US culture)
Console.WriteLine($"Price rounded: {price:F1}"); // Output: Price rounded: 123.5
Console.WriteLine($"Price with 2 decimals: {price:0.00}"); // Output: Price with 2 decimals: 123.45
Padding and Alignment
You can control spacing and alignment:
string[] fruits = { "Apple", "Banana", "Orange" };
decimal[] prices = { 1.2m, 0.85m, 2.0m };
Console.WriteLine($"{"Fruit",-10}{"Price",10}");
Console.WriteLine(new string('-', 20));
for (int i = 0; i < fruits.Length; i++)
{
Console.WriteLine($"{fruits[i],-10}{prices[i]:C,10}");
}
/* Output:
Fruit Price
--------------------
Apple $1.20
Banana $0.85
Orange $2.00
*/
The negative value -10
left-aligns with 10 character width, while positive 10
right-aligns.
Composite Formatting
Before string interpolation, the main approach was composite formatting using string.Format()
:
string firstName = "Jane";
string lastName = "Smith";
int age = 28;
string message = string.Format("Hello, my name is {0} {1} and I am {2} years old.",
firstName, lastName, age);
Console.WriteLine(message);
// Output: Hello, my name is Jane Smith and I am 28 years old.
The {0}
, {1}
, and {2}
are placeholders that get replaced by the values provided.
Format Specifiers
Format specifiers control how values appear:
double number = 1234.5678;
DateTime date = new DateTime(2023, 10, 15);
// Numeric formats
Console.WriteLine(string.Format("Currency: {0:C}", number)); // $1,234.57
Console.WriteLine(string.Format("Exponential: {0:E}", number)); // 1.234568E+003
Console.WriteLine(string.Format("Fixed-point: {0:F2}", number)); // 1234.57
Console.WriteLine(string.Format("General: {0:G}", number)); // 1234.5678
Console.WriteLine(string.Format("Number: {0:N}", number)); // 1,234.57
Console.WriteLine(string.Format("Percent: {0:P}", number/100)); // 12.35%
Console.WriteLine(string.Format("Hexadecimal: {0:X}", 255)); // FF
// Date formats
Console.WriteLine(string.Format("Short date: {0:d}", date)); // 10/15/2023
Console.WriteLine(string.Format("Long date: {0:D}", date)); // Sunday, October 15, 2023
Console.WriteLine(string.Format("Short time: {0:t}", date)); // 12:00 AM
Console.WriteLine(string.Format("Long time: {0:T}", date)); // 12:00:00 AM
Console.WriteLine(string.Format("Month: {0:MMM}", date)); // Oct
StringBuilder for Complex String Operations
When you need to perform many string operations, especially in loops, StringBuilder
is more efficient than concatenation:
using System.Text;
StringBuilder sb = new StringBuilder();
sb.Append("Hello ");
sb.Append("World");
sb.AppendLine("!");
sb.AppendFormat("The time is {0:t}", DateTime.Now);
string result = sb.ToString();
Console.WriteLine(result);
/*
Output:
Hello World!
The time is 3:45 PM
*/
Real-world Applications
Formatting a Receipt
string FormatReceipt(string storeName, string[] items, decimal[] prices, decimal taxRate)
{
StringBuilder receipt = new StringBuilder();
receipt.AppendLine($"*** {storeName} ***");
receipt.AppendLine($"Date: {DateTime.Now:MM/dd/yyyy hh:mm tt}");
receipt.AppendLine("---------------------------");
decimal subtotal = 0;
for (int i = 0; i < items.Length; i++)
{
receipt.AppendLine($"{items[i],-20}{prices[i],10:C}");
subtotal += prices[i];
}
decimal tax = subtotal * taxRate;
decimal total = subtotal + tax;
receipt.AppendLine("---------------------------");
receipt.AppendLine($"{"Subtotal",-20}{subtotal,10:C}");
receipt.AppendLine($"{"Tax",-20}{tax,10:C}");
receipt.AppendLine($"{"Total",-20}{total,10:C}");
receipt.AppendLine("---------------------------");
receipt.AppendLine("Thank you for your business!");
return receipt.ToString();
}
// Usage
string[] purchasedItems = { "Coffee", "Bagel", "Orange Juice" };
decimal[] itemPrices = { 3.50m, 2.75m, 4.25m };
Console.WriteLine(FormatReceipt("Morning Café", purchasedItems, itemPrices, 0.08m));
/* Output:
*** Morning Café ***
Date: 10/15/2023 03:45 PM
---------------------------
Coffee $3.50
Bagel $2.75
Orange Juice $4.25
---------------------------
Subtotal $10.50
Tax $0.84
Total $11.34
---------------------------
Thank you for your business!
*/
Formatting a Log Entry
string FormatLogEntry(string severity, string message, Exception exception = null)
{
string timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
if (exception != null)
{
return $"[{timestamp}] {severity}: {message}\nException: {exception.GetType().Name} - {exception.Message}\n{exception.StackTrace}";
}
else
{
return $"[{timestamp}] {severity}: {message}";
}
}
// Usage
Console.WriteLine(FormatLogEntry("INFO", "Application started"));
Console.WriteLine(FormatLogEntry("ERROR", "Failed to process file", new FileNotFoundException("Could not find file.txt")));
/* Output:
[2023-10-15 15:47:23.456] INFO: Application started
[2023-10-15 15:47:23.498] ERROR: Failed to process file
Exception: FileNotFoundException - Could not find file.txt
at Program.<Main>$(String[] args) in C:\Projects\Program.cs:line 25
*/
String Format Providers and Cultures
You can use IFormatProvider
to control formatting based on different cultures:
using System.Globalization;
double price = 1234.56;
DateTime date = new DateTime(2023, 10, 15);
// US culture
CultureInfo us = new CultureInfo("en-US");
Console.WriteLine($"US Price: {price.ToString("C", us)}"); // US Price: $1,234.56
Console.WriteLine($"US Date: {date.ToString("D", us)}"); // US Date: Sunday, October 15, 2023
// German culture
CultureInfo de = new CultureInfo("de-DE");
Console.WriteLine($"German Price: {price.ToString("C", de)}"); // German Price: 1.234,56 €
Console.WriteLine($"German Date: {date.ToString("D", de)}"); // German Date: Sonntag, 15. Oktober 2023
// Japanese culture
CultureInfo jp = new CultureInfo("ja-JP");
Console.WriteLine($"Japanese Price: {price.ToString("C", jp)}"); // Japanese Price: ¥1,235
Console.WriteLine($"Japanese Date: {date.ToString("D", jp)}"); // Japanese Date: 2023年10月15日
Summary
String formatting in C# provides powerful tools to create well-structured, readable text. In this guide, we covered:
- String concatenation for simple combinations
- String interpolation with
$"..."
for readable, inline formatting - Composite formatting with
string.Format()
and format specifiers StringBuilder
for efficient complex string operations- Format providers for culture-specific formatting
When deciding which approach to use:
- Use string interpolation (
$"..."
) for most scenarios due to its readability - Use
string.Format()
when you need to store format strings separately - Use
StringBuilder
when building strings in loops or with many operations - Always be mindful of culture-specific formatting when working with international applications
Exercises
- Create a method that formats a product description with name, price, and discount percentage.
- Write a function that generates an HTML table from a list of string arrays.
- Create a program that displays calendar events in different time zones with proper formatting.
- Implement a custom number formatting function that adds thousand separators and limits decimal places.
- Create a function that formats phone numbers according to different country standards.
Additional Resources
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)