String Operations

Discover the built-in methods used to compare, search, format, and manipulate text data in C#.

The System.String class provides dozens of built-in methods. Let's look at some of the most critical operations that we can perform on string objects.

Compare

We can compare the equality of strings or their alphabetical ordering. To check alphabetical sequence, we use the CompareTo() method.

C# 14.0
string person1 = "Anna";
string person2 = "Darcy";
// Checking for equality
bool areSame = person1 == person2;
Console.WriteLine($"Same: {areSame}.");
// Negative result: person1 is before person2 (in terms of alphabetical order)
// Zero: person1 and person2 have the same position
// Positive result: person1 is after person2
int comparisonResult = person1.CompareTo(person2);
// Comparison result is negative because A precedes D
Console.WriteLine(comparisonResult);
person2 = "Albert";
comparisonResult = person1.CompareTo(person2);
// Now, the result is positive because An comes after Al
Console.WriteLine(comparisonResult);
  • Lines 1–2: We define two separate string variables representing names.

  • Lines 5–6: We evaluate if both strings are identical and print the resulting boolean value.

  • Lines 12–15: We execute CompareTo() to check alphabetical ordering. This prints a negative number since “Anna” comes before “Darcy”.

  • Lines 17–21: We update the second name to “Albert” and compare again. This yields a positive integer because “Anna” comes after “Albert”.

Culture-aware comparisons

Using the == operator performs an exact, case-sensitive match. When we need to compare strings without case sensitivity, we should avoid converting both strings using .ToLower() or .ToUpper(). Creating new strings just for comparison wastes memory. Instead, we use the string.Equals() method combined with the StringComparison.OrdinalIgnoreCase enumeration.

C# 14.0
string userInput = "ADMIN";
string targetRole = "admin";
// Inefficient approach (creates new memory allocations)
bool inefficientMatch = userInput.ToLower() == targetRole.ToLower();
Console.WriteLine($"Matched inefficiently: {inefficientMatch}");
// Modern, memory-efficient approach
bool efficientMatch = string.Equals(userInput, targetRole, StringComparison.OrdinalIgnoreCase);
Console.WriteLine($"Matched securely: {efficientMatch}");
  • Lines 1–2: We define two strings with identical text but different casing.

  • Line 5: We show the inefficient approach. Calling ToLower() allocates two completely new string objects in memory just to perform a check.

  • Line 6: We print the result of the inefficient match.

  • Line 9: We use string.Equals with StringComparison.OrdinalIgnoreCase to perform a direct, allocation-free comparison.

  • Line 10: We print the result of our secure, efficient match.

Note: Text characters can sometimes look identical on screen but consist of different underlying Unicode bytes. We can call the .Normalize() method on a string before comparing it to ensure the underlying byte representations align correctly across different language cultures.

Combine

Combining strings is also known as concatenation. While traditional methods like the + operator and string.Concat are valid, modern C# heavily utilizes string interpolation ($"") as the default approach for readability.

String concatenation
String concatenation

Here is how we can implement these different combining techniques.

C# 14.0
string firstName = "Albert";
string lastName = "Johnson";
// Three ways to combine strings
string fullName = firstName + " " + lastName;
string fullName1 = string.Concat(firstName, " ", lastName);
string fullName2 = $"{firstName} {lastName}"; // String interpolation
Console.WriteLine(fullName);
Console.WriteLine(fullName1);
Console.WriteLine(fullName2);
// We can also join an array of strings with a delimiter
string[] names = ["Robert", "Dan", "Luke", "Marcus"];
string allNames = string.Join(", ", names);
Console.WriteLine(allNames);
  • Lines 1–2: We establish two separate string variables for the first and last names.

  • Line 5: We concatenate the strings using the basic + operator.

  • Line 6: We merge the strings using the built-in string.Concat method.

  • Line 7: We construct the final string using modern string interpolation. This approach is highly recommended for clarity.

  • Lines 9–11: We print all three identically formatted results to the console.

  • Lines 14–16: We declare an array of names and seamlessly join them together using a comma delimiter.

String interpolation formatting

String interpolation ($"") does more than just combine variables. We can append format specifiers directly inside the curly braces to automatically format numbers, dates, and currency.

C# 14.0
double price = 1499.99;
double discount = 0.15;
// The :C specifier formats as local currency
// The :P0 specifier formats as a percentage with zero decimal places
string receipt = $"Total: {price:C} (Includes {discount:P0} discount)";
Console.WriteLine(receipt);
  • Lines 1–2: We declare two standard numeric variables.

  • Line 6: We construct an interpolated string. We add :C to format the price as currency and :P0 to format the decimal as a whole-number percentage.

  • Line 8: We print the formatted receipt to the console.

Note: The :C specifier depends on your system’s regional settings. If your environment is not configured for a specific country, you may see the generic currency symbol (¤) instead of a specific sign like $ or .

Searching

We can use the IndexOf() method to check if a string contains a certain substring. It returns the index of the first character of the searched substring. If there are no matches, the result is negative.

We use conditional logic to react to the presence or absence of the targeted phrase.

C# 14.0
var story = "The girl looked for a candy but didn't succeed.";
// We are looking for "girl" substring
var girlIndex = story.IndexOf("girl");
// If there is a match
if (girlIndex != -1)
{
Console.WriteLine($"The word 'girl' exists in the text. Its position is {girlIndex}.");
}
else
{
Console.WriteLine("Couldn't find 'girl' in the text.");
}
  • Line 1: We declare a string variable holding a short sentence.

  • Line 4: We search for the precise starting index of the word “girl”.

  • Lines 7–14: We check if the returned index is valid (not -1). We output the calculated position if it exists.

Checking the beginning and end

Often, we don’t need to know exactly where a substring is located; we only need to know if the string begins or ends with a specific pattern. The StartsWith() and EndsWith() methods return a simple boolean value for this exact purpose.

C# 14.0
string website = "https://www.educative.io";
bool isSecure = website.StartsWith("https://");
bool isOrg = website.EndsWith(".org");
Console.WriteLine($"Is secure: {isSecure}"); // True
Console.WriteLine($"Is .org domain: {isOrg}"); // False
  • Line 1: We define a string representing a URL.

  • Line 3: We use StartsWith to verify if the URL uses a secure protocol.

  • Line 4: We use EndsWith to check if the domain belongs to an organization.

  • Lines 6–7: We print the resulting boolean values.

Trim

Strings often contain unwanted leading or trailing characters, such as extra whitespace. Trimming methods remove these unwanted characters from the edges of a string. We can use the Trim(), TrimStart(), and TrimEnd() methods.

C# 14.0
var text = " ###The girl looked for candy but didn't succeed.## ";
Console.WriteLine(text);
// Trim() removes whitespaces from both ends
text = text.Trim();
Console.WriteLine(text);
// Remove the designated character from both ends of the string
Console.WriteLine(text.Trim('#'));
// We can also target just the beginning or the end
Console.WriteLine(text.TrimStart('#'));
Console.WriteLine(text.TrimEnd('#'));
  • Line 1: We define a string containing padding spaces and hash characters.

  • Line 5: We utilize the standard Trim() method to remove all leading and trailing whitespace.

  • Line 9: We call Trim('#') to strip the specific hash characters from both ends of the updated string.

  • Lines 12–13: We use TrimStart and TrimEnd to remove the hash characters from only the beginning or only the end of the string, respectively.

Demonstrating the trim methods
Demonstrating the trim methods

The text now looks clean.

Substring

We can use the Substring() method if we only want a specific part of the string.

Demonstrating the Substring methods
Demonstrating the Substring methods

We can extract it by providing starting indexes and lengths.

C# 14.0
var text = "Hello, this amazing world!";
// Take the substring starting from the index 7 till the end of the string
Console.WriteLine(text.Substring(7)); // this amazing world!
// Take a substring of length 7 starting from the index 5
Console.WriteLine(text.Substring(12, 7)); // amazing
  • Line 1: We instantiate the original text variable.

  • Line 4: We capture all characters starting from index 7 through to the very end of the string.

  • Line 7: We extract exactly 7 characters starting directly from index 12.

Split

Splitting is another common operation. We can split a string into an array of substrings using the Split() method. This method is useful when we need to process each word in the text separately.

Demonstrating the split method
Demonstrating the split method

Consider the following scenario. We want to capitalize each word in a user-provided text. We can first split the text into an array of individual words, capitalize each word, and then join the array back.

The Split() method can accept a character that it will use to split the string. By default, it splits based on space.

Let’s implement this text normalization routine and explore different delimiters.

C# 14.0
var text = "I want to play some game.";
// Splitting the string into an array of strings by spaces
var words = text.Split();
// To see the resulting pieces, we can join them back together with a visible separator
Console.WriteLine(string.Join(" | ", words));
for (int i = 0; i < words.Length; i++)
{
// Capitalize the first character of the word,
// and then assemble a new word (Capitalized character + word without the first letter)
words[i] = char.ToUpper(words[i][0]) + words[i].Substring(1);
}
// Combine the string array back into a string
Console.WriteLine(string.Join(" ", words));
// We can split by a specific character and view the parts
Console.WriteLine(string.Join(" | ", text.Split('a')));
// We can also split by an entire string
Console.WriteLine(string.Join(" | ", text.Split("play")));
  • Line 1: We prepare a fully lowercase sentence.

  • Line 4: We segment the text at every space, generating an array of words.

  • Line 7: We join and print the split array with a pipe separator to visualize the individual elements.

  • Lines 19–14: We loop through each array element, capitalize the first character, and append the remaining substring.

  • Line 17: We reassemble the array into a single string using spaces and print the result.

  • Line 20: We split the original text using the character 'a' as the delimiter and display the segments.

  • Line 23: We split the original text using the string "play" as the delimiter and display the results.

Insert, remove, and replace

There are also methods that allow us to insert a character to a given position, remove a character, or replace it with a different one. These methods let us modify string contents. We must remember that each operation allocates a new string object in memory.

C# 14.0
var textWithMistake = "Hello orld!";
Console.WriteLine(textWithMistake);
// We can insert a string to a certain index
var textWithoutMistake = textWithMistake.Insert(6, "w");
Console.WriteLine(textWithoutMistake);
// We can replace a character with a different character
// or replace a substring with a different substring
var exclamation = textWithoutMistake.Replace("!", "!!!");
Console.WriteLine(exclamation);
// We can remove some part of a string
var startingIndex = exclamation.IndexOf(" world");
exclamation = exclamation.Remove(startingIndex, " world".Length);
Console.WriteLine(exclamation);
  • Line 2: We define the initial string containing a missing character (“w”).

  • Line 6: We insert the missing ‘w’ exactly at the 6th index of the sequence, fixing the mistake.

  • Line 11: We swap out the single exclamation mark for three exclamation marks using the replace method.

  • Lines 15–16: We locate the starting index of the phrase “ world” and completely remove it based on its calculated length.

Changing case and capitalization

We often need to standardize text input by converting it entirely to uppercase or lowercase. The ToUpper() and ToLower() methods handle these full-string conversions. However, to capitalize only the very first letter of a string, we must combine the char.ToUpper() method with string indexing and the Substring() method.

C# 14.0
string title = "welcome to the application";
// Convert the entire string to uppercase
string upperTitle = title.ToUpper();
Console.WriteLine(upperTitle);
// Convert the entire string to lowercase
string lowerTitle = upperTitle.ToLower();
Console.WriteLine(lowerTitle);
// Capitalize only the first letter safely
if (!string.IsNullOrEmpty(title))
{
string capitalizedTitle = char.ToUpper(title[0]) + title.Substring(1);
Console.WriteLine(capitalizedTitle);
}
  • Lines 4–9: We demonstrate standard methods to convert the entire string to either uppercase or lowercase. Each method call allocates a new string in memory.

  • Lines 12–16: We verify the string is not empty before attempting to read the first character. We then capitalize the first character using char.ToUpper(title[0]) and concatenate it with the remainder of the string using title.Substring(1).