C# strings and formatting
Use common string methods, compare text correctly, and format numbers with format specifiers.
On this page
C# variables and Console.WriteLine.
- Use common string methods, compare text correctly, and format numbers with format specifiers.
- Predict the sample output and explain the state changes.
- Complete the practice task and check the boundary cases.
The concept
A C# string is an immutable sequence of characters, so methods such as Substring, Replace, and ToUpper return new strings. Split turns a string into an array, string.Join does the reverse, and Trim and PadLeft change the white space around the text. StringBuilder is the right tool for building a long string in a loop, because it does not copy the text on every append.
The == operator on strings compares the characters, and it is case-sensitive. For case-insensitive comparison use string.Equals with StringComparison.OrdinalIgnoreCase. Interpolated strings, written $"...", can include format specifiers after a colon: F2 for two decimals, N0 for a thousands separator, D5 for five digits with leading zeros, and X for hexadecimal. Formatting depends on the culture, so FormattableString.Invariant fixes the output regardless of the computer's settings.
Code example
using System;
using System.Text;
class Program {
static void Main() {
string name = "Programonic";
Console.WriteLine(name.Length + " " + name.Substring(0, 7) + " " + name.IndexOf('m'));
Console.WriteLine(name.ToUpper() + " " + name.Replace("o", "0"));
string[] parts = "a,b,,c".Split(',');
Console.WriteLine(parts.Length + " " + string.Join("-", parts));
Console.WriteLine(" padded ".Trim().PadLeft(8, '*'));
Console.WriteLine("apple" == "APPLE");
Console.WriteLine(string.Equals("apple", "APPLE", StringComparison.OrdinalIgnoreCase));
double price = 1234.56;
Console.WriteLine(FormattableString.Invariant($"{price:F2} {price:N0} {42:D5} {255:X}"));
var builder = new StringBuilder();
for (int i = 1; i <= 3; i++) {
builder.Append(i).Append(i < 3 ? "," : "");
}
Console.WriteLine(builder);
}
}11 Program 6 PROGRAMONIC Pr0gram0nic 4 a-b--c **padded False True 1234.56 1,235 00042 FF 1,2,3
Follow the code
Open the walkthrough to inspect the example one step at a time.
Show guided walkthrough
using System;using System.Text; class Program { static void Main() { string name = "Programonic"; Console.WriteLine(name.Length + " " + name.Substring(0, 7) + " " + name.IndexOf('m')); Console.WriteLine(name.ToUpper() + " " + name.Replace("o", "0")); string[] parts = "a,b,,c".Split(','); Console.WriteLine(parts.Length + " " + string.Join("-", parts)); Console.WriteLine(" padded ".Trim().PadLeft(8, '*')); Console.WriteLine("apple" == "APPLE"); Console.WriteLine(string.Equals("apple", "APPLE", StringComparison.OrdinalIgnoreCase)); double price = 1234.56; Console.WriteLine(FormattableString.Invariant($"{price:F2} {price:N0} {42:D5} {255:X}")); var builder = new StringBuilder(); for (int i = 1; i <= 3; i++) { builder.Append(i).Append(i < 3 ? "," : ""); } Console.WriteLine(builder); }}Follow the example
Start to inspect the source, values, and output. These prepared steps explain the published sample; grouped loop steps describe multiple iterations.
View the complete dry-run table
| Step / line | What happens | State after step | Output so far |
|---|---|---|---|
| Length 11, the first seven characters, and the index of the first m. | — | 11 Program 6 | |
| Both methods return new strings; name itself is unchanged. | — | 11 Program 6 PROGRAMONIC Pr0gram0nic | |
| Split keeps the empty entry between the commas. | — | 11 Program 6 PROGRAMONIC Pr0gram0nic 4 a-b--c | |
| Trim removes the spaces; PadLeft fills the left side up to width 8. | — | 11 Program 6 PROGRAMONIC Pr0gram0nic 4 a-b--c **padded | |
| == is case-sensitive. | — | 11 Program 6 PROGRAMONIC Pr0gram0nic 4 a-b--c **padded False | |
| Explicit comparison option ignores the case. | — | 11 Program 6 PROGRAMONIC Pr0gram0nic 4 a-b--c **padded False True | |
| Fixed-point with 2 decimals, thousands separator with no decimals, five-digit zero padding, and hexadecimal. | — | 11 Program 6 PROGRAMONIC Pr0gram0nic 4 a-b--c **padded False True 1234.56 1,235 00042 FF | |
| StringBuilder built the text without creating a new string on every append. | — | 11 Program 6 PROGRAMONIC Pr0gram0nic 4 a-b--c **padded False True 1234.56 1,235 00042 FF 1,2,3 |
Behind the scenes
How C# processes this code
C# compiles to code for the .NET runtime, which invokes the program entry point.
Cost and common mistakes
Most string operations are O(n) in the length of the text.
- Using + in a loop to build a long string creates a new string every time, which is O(n²) overall. Use StringBuilder.
- Without an explicit culture, number formatting follows the computer's regional settings, so the same program can print 1,234.50 or 1.234,50.
- Use the Ordinal comparisons for identifiers and file names, and culture-aware comparisons only for text shown to people.
Try it yourself
How would you print 7 as 007?
Reveal answer and reasoning
Use the D3 format specifier: 7.ToString("D3") gives 007.