Skip to content

C# - Strings

In C#, a string is a sequence of characters used to represent text. It is an alias for the System.String class. Strings are one of the most fundamental and commonly used types in any application. A key characteristic of C# strings is that they are immutable: once a string object is created, its value cannot be changed. Any operation that appears to modify a string actually creates a new string object.

You can create strings in several ways, but the most common are using literals and string interpolation.

using System;
using System.Text;
// 1. Using a string literal
var greeting = "Hello, World!";
// 2. String Interpolation (the modern, preferred way to format)
var user = "Alice";
var score = 120;
var welcomeMessage = $"Welcome, {user}! Your score is {score}.";
// 3. Verbatim string literals (for paths, multi-line text)
var filePath = @"C:\Users\Default\Documents";
var multiLine = @"This is a string
that spans multiple
lines.";
// 4. Raw string literals (C# 11+, for JSON, XML, etc.)
var json = """
{
"name": "Bob",
"score": 95
}
""";
Console.WriteLine(greeting);
Console.WriteLine(welcomeMessage);
Console.WriteLine(filePath);

The string class provides a rich set of methods and properties for manipulation.

using System;
var text = " Modern C# Programming ";
// Get length
Console.WriteLine($"Length: {text.Length}"); // Output: 25
// Change case
Console.WriteLine($"Uppercase: {text.ToUpper()}");
Console.WriteLine($"Lowercase: {text.ToLower()}");
// Trim whitespace
var trimmedText = text.Trim();
Console.WriteLine($"Trimmed: '{trimmedText}'"); // Output: 'Modern C# Programming'
// Substring and Ranges (C# 8+)
var language = trimmedText.Substring(7, 2); // (startIndex, length)
var modernWay = trimmedText[7..9]; // Using Range operator
Console.WriteLine($"Substring: {language}"); // Output: C#
Console.WriteLine($"Range: {modernWay}"); // Output: C#
// Searching
bool containsCSharp = trimmedText.Contains("C#");
bool startsWithModern = trimmedText.StartsWith("Modern");
bool endsWithProgramming = trimmedText.EndsWith("Programming");
Console.WriteLine($"Contains 'C#': {containsCSharp}"); // Output: True
// Replace
var newText = trimmedText.Replace("Modern", "Advanced");
Console.WriteLine($"Replaced: {newText}"); // Output: Advanced C# Programming

Comparing strings correctly is crucial. Using == performs a case-sensitive, ordinal (byte-by-byte) comparison. For more control, especially with user input, use the string.Equals method.

var str1 = "hello";
var str2 = "HELLO";
// Case-sensitive comparison (will be false)
Console.WriteLine($"'hello' == 'HELLO': {str1 == str2}");
// BEST PRACTICE: Case-insensitive comparison
bool areEqual = string.Equals(str1, str2, StringComparison.OrdinalIgnoreCase);
Console.WriteLine($"Are they equal (case-insensitive)?: {areEqual}");

Best Practice: Always specify a StringComparison type when comparing strings from different sources (like user input or external APIs) to avoid subtle bugs related to culture and case sensitivity. OrdinalIgnoreCase is usually the safest and most performant choice for non-linguistic comparisons.

In C#, a string can be null, empty (""), or consist only of whitespace. The string.IsNullOrWhiteSpace method is the most robust way to check for any of these states.

string? input1 = null;
string input2 = "";
string input3 = " ";
string input4 = "some text";
Console.WriteLine($"Input 1 is null or whitespace: {string.IsNullOrWhiteSpace(input1)}"); // True
Console.WriteLine($"Input 2 is null or whitespace: {string.IsNullOrWhiteSpace(input2)}"); // True
Console.WriteLine($"Input 3 is null or whitespace: {string.IsNullOrWhiteSpace(input3)}"); // True
Console.WriteLine($"Input 4 is null or whitespace: {string.IsNullOrWhiteSpace(input4)}"); // False

Because strings are immutable, repeatedly concatenating them in a loop is very inefficient. Each concatenation creates a new string object, leading to high memory allocation and garbage collection pressure. For building strings programmatically, especially in loops, always use the System.Text.StringBuilder class.

using System.Text;
// Inefficient way - AVOID in loops
string numbersStr = "";
for (int i = 1; i <= 5; i++) {
numbersStr += i.ToString() + " "; // Creates 5 new string objects
}
// Efficient way - USE StringBuilder
var sb = new StringBuilder();
for (int i = 1; i <= 5; i++) {
sb.Append(i).Append(' '); // Modifies the internal buffer
}
string result = sb.ToString(); // Create the final string only once
Console.WriteLine($"Inefficient result: {numbersStr}");
Console.WriteLine($"Efficient result: {result}");

String.Join is a highly efficient way to construct a single string from a collection of strings. Split does the opposite.

// Joining
var items = new[] { "Apples", "Oranges", "Bananas" };
var csv = string.Join(", ", items);
Console.WriteLine($"CSV: {csv}"); // Output: CSV: Apples, Oranges, Bananas
// Splitting
var tags = "c#,dotnet,programming";
string[] tagArray = tags.Split(',');
Console.WriteLine("Tags found:");
foreach (var tag in tagArray)
{
Console.WriteLine($"- {tag}");
}