4.4 - Working with Strings
Strings are one of the most commonly used data types in programming. In C#, strings are objects of the System.String
class, which provides a rich set of methods for string manipulation. This chapter explores various aspects of working with strings in C#.
4.4.1 - String Creation and Manipulation
C# provides multiple ways to create and manipulate strings, from basic string literals to more complex operations.
4.4.1.1 - Creating Strings
There are several ways to create strings in C#:
Example:
using System;
using System.Text;
class Program
{
static void Main()
{
// String literals
string str1 = "Hello, World!";
// String concatenation
string str2 = "Hello, " + "World!";
// String constructor
char[] chars = { 'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!' };
string str3 = new string(chars);
// String.Empty
string emptyString = string.Empty; // Same as ""
// null string
string nullString = null;
// Verbatim string literal (preserves whitespace and newlines)
string verbatimString = @"This is a verbatim string.
It can span multiple lines
and preserves whitespace.";
// String interpolation (C# 6.0 and later)
string name = "Alice";
string greeting = $"Hello, {name}!";
// Raw string literals (C# 11 and later)
string rawString = """
This is a raw string literal.
It can contain "quotes" without escaping.
""";
// UTF-8 string literals (C# 11 and later)
ReadOnlySpan<byte> utf8Bytes = "Hello, UTF-8!"u8;
// Display the strings
Console.WriteLine(str1);
Console.WriteLine(str2);
Console.WriteLine(str3);
Console.WriteLine($"Empty string: '{emptyString}'");
Console.WriteLine($"Null string: '{nullString}'");
Console.WriteLine(verbatimString);
Console.WriteLine(greeting);
Console.WriteLine(rawString);
Console.WriteLine($"UTF-8 bytes length: {utf8Bytes.Length}");
Console.WriteLine($"UTF-8 string: {Encoding.UTF8.GetString(utf8Bytes)}");
}
}
4.4.1.2 - String Properties
The String
class provides several properties that give information about a string:
Example:
using System;
class Program
{
static void Main()
{
string text = "Hello, World!";
// Length property
Console.WriteLine($"Length: {text.Length}");
// Accessing individual characters
Console.WriteLine($"First character: {text[0]}");
Console.WriteLine($"Last character: {text[text.Length - 1]}");
// Checking if a string is null or empty
string emptyString = "";
string nullString = null;
Console.WriteLine($"Is text null or empty? {string.IsNullOrEmpty(text)}");
Console.WriteLine($"Is emptyString null or empty? {string.IsNullOrEmpty(emptyString)}");
Console.WriteLine($"Is nullString null or empty? {string.IsNullOrEmpty(nullString)}");
// Checking if a string is null, empty, or consists only of white-space characters
string whitespaceString = " ";
Console.WriteLine($"Is whitespaceString null or whitespace? {string.IsNullOrWhiteSpace(whitespaceString)}");
}
}
4.4.1.3 - String Manipulation Methods
The String
class provides numerous methods for manipulating strings:
Example:
using System;
class Program
{
static void Main()
{
string text = "Hello, World!";
// Substring
string sub1 = text.Substring(7); // "World!"
string sub2 = text.Substring(0, 5); // "Hello"
Console.WriteLine($"Substring from index 7: '{sub1}'");
Console.WriteLine($"Substring from index 0, length 5: '{sub2}'");
// Replace
string replaced = text.Replace("World", "C#");
Console.WriteLine($"After replacing 'World' with 'C#': '{replaced}'");
// Insert
string inserted = text.Insert(7, "Beautiful ");
Console.WriteLine($"After inserting 'Beautiful ' at index 7: '{inserted}'");
// Remove
string removed = text.Remove(5); // Remove everything from index 5 onwards
Console.WriteLine($"After removing from index 5: '{removed}'");
string removed2 = text.Remove(5, 2); // Remove 2 characters starting from index 5
Console.WriteLine($"After removing 2 characters from index 5: '{removed2}'");
// Trim, TrimStart, TrimEnd
string paddedText = " Padded Text ";
Console.WriteLine($"Original: '{paddedText}'");
Console.WriteLine($"After Trim: '{paddedText.Trim()}'");
Console.WriteLine($"After TrimStart: '{paddedText.TrimStart()}'");
Console.WriteLine($"After TrimEnd: '{paddedText.TrimEnd()}'");
// PadLeft, PadRight
string shortText = "42";
Console.WriteLine($"Original: '{shortText}'");
Console.WriteLine($"After PadLeft(5): '{shortText.PadLeft(5)}'");
Console.WriteLine($"After PadLeft(5, '0'): '{shortText.PadLeft(5, '0')}'");
Console.WriteLine($"After PadRight(5, '*'): '{shortText.PadRight(5, '*')}'");
// ToUpper, ToLower
Console.WriteLine($"Original: '{text}'");
Console.WriteLine($"ToUpper: '{text.ToUpper()}'");
Console.WriteLine($"ToLower: '{text.ToLower()}'");
}
}
4.4.1.4 - Splitting and Joining Strings
C# provides methods for splitting a string into an array of substrings and joining an array of strings into a single string:
Example:
using System;
class Program
{
static void Main()
{
// Split
string csvLine = "Alice,Bob,Charlie,David";
string[] names = csvLine.Split(',');
Console.WriteLine("Names after splitting:");
foreach (string name in names)
{
Console.WriteLine($" {name}");
}
// Split with options
string text = "One Two Three";
string[] words = text.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
Console.WriteLine("\nWords after splitting with RemoveEmptyEntries:");
foreach (string word in words)
{
Console.WriteLine($" {word}");
}
// Join
string[] fruits = { "Apple", "Banana", "Cherry", "Date" };
string joinedString = string.Join(", ", fruits);
Console.WriteLine($"\nJoined string: {joinedString}");
// Join with different separator
string joinedWithPipe = string.Join(" | ", fruits);
Console.WriteLine($"Joined with pipe: {joinedWithPipe}");
// Join a range of array elements
string joinedRange = string.Join("-", fruits, 1, 2); // Join 2 elements starting from index 1
Console.WriteLine($"Joined range: {joinedRange}");
}
}
4.4.1.5 - Searching within Strings
The String
class provides methods for searching within strings:
Example:
using System;
class Program
{
static void Main()
{
string text = "The quick brown fox jumps over the lazy dog";
// Contains
bool containsFox = text.Contains("fox");
bool containsCat = text.Contains("cat");
Console.WriteLine($"Contains 'fox': {containsFox}");
Console.WriteLine($"Contains 'cat': {containsCat}");
// StartsWith, EndsWith
bool startsWithThe = text.StartsWith("The");
bool endsWithDog = text.EndsWith("dog");
Console.WriteLine($"Starts with 'The': {startsWithThe}");
Console.WriteLine($"Ends with 'dog': {endsWithDog}");
// IndexOf, LastIndexOf
int indexOfFox = text.IndexOf("fox");
int indexOfThe = text.IndexOf("the");
int lastIndexOfThe = text.LastIndexOf("the");
Console.WriteLine($"Index of 'fox': {indexOfFox}");
Console.WriteLine($"Index of 'the': {indexOfThe}");
Console.WriteLine($"Last index of 'the': {lastIndexOfThe}");
// IndexOf with start index and count
int indexOfO = text.IndexOf('o', 10); // Start searching from index 10
int indexOfO2 = text.IndexOf('o', 10, 10); // Start searching from index 10, search in next 10 characters
Console.WriteLine($"Index of 'o' starting from index 10: {indexOfO}");
Console.WriteLine($"Index of 'o' starting from index 10, searching 10 characters: {indexOfO2}");
// IndexOfAny
char[] vowels = { 'a', 'e', 'i', 'o', 'u' };
int indexOfFirstVowel = text.IndexOfAny(vowels);
Console.WriteLine($"Index of first vowel: {indexOfFirstVowel} ('{text[indexOfFirstVowel]}')");
}
}
4.4.2 - String Formatting
C# provides several ways to format strings, making it easier to create strings with dynamic content.
4.4.2.1 - Composite Formatting
Composite formatting uses numbered placeholders in a format string, which are replaced with the corresponding arguments:
Example:
using System;
class Program
{
static void Main()
{
string name = "Alice";
int age = 30;
double height = 1.75;
// Basic composite formatting
string message = string.Format("Name: {0}, Age: {1}, Height: {2}m", name, age, height);
Console.WriteLine(message);
// Reusing placeholders
string repeated = string.Format("{0} is {1} years old. {0} is {2}m tall.", name, age, height);
Console.WriteLine(repeated);
// Formatting with alignment
string aligned = string.Format("{0,-10} {1,5} {2,8}", "Name", "Age", "Height");
string data = string.Format("{0,-10} {1,5} {2,8:F2}", name, age, height);
Console.WriteLine(aligned);
Console.WriteLine(data);
// Formatting with different format specifiers
string formatted = string.Format("Currency: {0:C}, Percent: {1:P}, Date: {2:d}",
123.45, 0.75, DateTime.Now);
Console.WriteLine(formatted);
// Direct use with Console.WriteLine
Console.WriteLine("Name: {0}, Age: {1}, Height: {2}m", name, age, height);
}
}
4.4.2.2 - Format Specifiers
Format specifiers allow you to control how values are formatted:
Example:
using System;
class Program
{
static void Main()
{
// Numeric format specifiers
double number = 1234.5678;
Console.WriteLine("Numeric format specifiers:");
Console.WriteLine($"C (Currency): {number:C}");
Console.WriteLine($"D (Decimal): {(int)number:D6}");
Console.WriteLine($"E (Exponential): {number:E}");
Console.WriteLine($"F (Fixed-point): {number:F2}");
Console.WriteLine($"G (General): {number:G}");
Console.WriteLine($"N (Number): {number:N}");
Console.WriteLine($"P (Percent): {number / 100:P}");
Console.WriteLine($"X (Hexadecimal): {(int)number:X}");
// Date and time format specifiers
DateTime now = DateTime.Now;
Console.WriteLine("\nDate and time format specifiers:");
Console.WriteLine($"d (Short date): {now:d}");
Console.WriteLine($"D (Long date): {now:D}");
Console.WriteLine($"t (Short time): {now:t}");
Console.WriteLine($"T (Long time): {now:T}");
Console.WriteLine($"f (Full date/time, short time): {now:f}");
Console.WriteLine($"F (Full date/time, long time): {now:F}");
Console.WriteLine($"g (General date/time, short time): {now:g}");
Console.WriteLine($"G (General date/time, long time): {now:G}");
Console.WriteLine($"M (Month/day): {now:M}");
Console.WriteLine($"Y (Year/month): {now:Y}");
// Custom format specifiers
Console.WriteLine("\nCustom format specifiers:");
Console.WriteLine($"Custom numeric: {number:#,##0.000}");
Console.WriteLine($"Custom date: {now:yyyy-MM-dd HH:mm:ss}");
}
}
4.4.2.3 - Formatting with IFormatProvider
The IFormatProvider
interface allows you to control formatting based on culture-specific information:
Example:
using System;
using System.Globalization;
class Program
{
static void Main()
{
double number = 1234.56;
DateTime date = new DateTime(2023, 4, 15);
// Format using different cultures
CultureInfo[] cultures = {
CultureInfo.GetCultureInfo("en-US"),
CultureInfo.GetCultureInfo("fr-FR"),
CultureInfo.GetCultureInfo("de-DE"),
CultureInfo.GetCultureInfo("ja-JP")
};
Console.WriteLine("Formatting with different cultures:");
foreach (var culture in cultures)
{
Console.WriteLine($"Culture: {culture.DisplayName}");
Console.WriteLine($" Number: {number.ToString("C", culture)}");
Console.WriteLine($" Date: {date.ToString("D", culture)}");
}
// Format using the invariant culture
Console.WriteLine("\nFormatting with invariant culture:");
Console.WriteLine($" Number: {number.ToString("C", CultureInfo.InvariantCulture)}");
Console.WriteLine($" Date: {date.ToString("D", CultureInfo.InvariantCulture)}");
}
}
4.4.3 - String Comparison
Comparing strings in C# requires careful consideration of case sensitivity, culture, and other factors.
4.4.3.1 - Basic String Comparison
C# provides several ways to compare strings:
Example:
using System;
class Program
{
static void Main()
{
string str1 = "Hello";
string str2 = "hello";
string str3 = "Hello";
// Equality operators
bool equal1 = (str1 == str2); // Case-sensitive comparison
bool equal2 = (str1 == str3);
Console.WriteLine($"str1 == str2: {equal1}");
Console.WriteLine($"str1 == str3: {equal2}");
// String.Equals method
bool equals1 = str1.Equals(str2); // Case-sensitive comparison
bool equals2 = str1.Equals(str2, StringComparison.OrdinalIgnoreCase); // Case-insensitive comparison
Console.WriteLine($"str1.Equals(str2): {equals1}");
Console.WriteLine($"str1.Equals(str2, StringComparison.OrdinalIgnoreCase): {equals2}");
// String.Compare method
int compare1 = string.Compare(str1, str2); // Case-sensitive comparison
int compare2 = string.Compare(str1, str2, true); // Case-insensitive comparison
Console.WriteLine($"string.Compare(str1, str2): {compare1}");
Console.WriteLine($"string.Compare(str1, str2, true): {compare2}");
// Interpreting Compare results
if (compare1 < 0)
Console.WriteLine("str1 comes before str2");
else if (compare1 > 0)
Console.WriteLine("str1 comes after str2");
else
Console.WriteLine("str1 and str2 are equal");
}
}
4.4.3.2 - String Comparison with StringComparison
The StringComparison
enumeration provides options for controlling string comparison behavior:
Example:
using System;
class Program
{
static void Main()
{
string str1 = "Hello";
string str2 = "hello";
// Different StringComparison options
Console.WriteLine("String comparison with different StringComparison options:");
// Ordinal comparison (binary comparison based on character values)
bool ordinal = str1.Equals(str2, StringComparison.Ordinal);
Console.WriteLine($"Ordinal: {ordinal}");
// Ordinal case-insensitive comparison
bool ordinalIgnoreCase = str1.Equals(str2, StringComparison.OrdinalIgnoreCase);
Console.WriteLine($"OrdinalIgnoreCase: {ordinalIgnoreCase}");
// Current culture comparison
bool currentCulture = str1.Equals(str2, StringComparison.CurrentCulture);
Console.WriteLine($"CurrentCulture: {currentCulture}");
// Current culture case-insensitive comparison
bool currentCultureIgnoreCase = str1.Equals(str2, StringComparison.CurrentCultureIgnoreCase);
Console.WriteLine($"CurrentCultureIgnoreCase: {currentCultureIgnoreCase}");
// Invariant culture comparison
bool invariantCulture = str1.Equals(str2, StringComparison.InvariantCulture);
Console.WriteLine($"InvariantCulture: {invariantCulture}");
// Invariant culture case-insensitive comparison
bool invariantCultureIgnoreCase = str1.Equals(str2, StringComparison.InvariantCultureIgnoreCase);
Console.WriteLine($"InvariantCultureIgnoreCase: {invariantCultureIgnoreCase}");
}
}
4.4.3.3 - Culture-Sensitive String Comparison
String comparison can be affected by culture-specific rules:
Example:
using System;
using System.Globalization;
class Program
{
static void Main()
{
// Culture-sensitive comparison examples
string s1 = "Strasse";
string s2 = "Straße"; // German sharp s (ß) is equivalent to "ss" in some contexts
// Compare using different cultures
CultureInfo germanCulture = CultureInfo.GetCultureInfo("de-DE");
// Ordinal comparison (binary comparison)
int ordinalComparison = string.Compare(s1, s2, StringComparison.Ordinal);
Console.WriteLine($"Ordinal comparison: {ordinalComparison}");
// Culture-sensitive comparison
int germanComparison = string.Compare(s1, s2, false, germanCulture);
Console.WriteLine($"German culture comparison: {germanComparison}");
// Another example with accented characters
string e1 = "resume";
string e2 = "résumé";
int englishComparison = string.Compare(e1, e2, false, CultureInfo.GetCultureInfo("en-US"));
int frenchComparison = string.Compare(e1, e2, false, CultureInfo.GetCultureInfo("fr-FR"));
Console.WriteLine($"English culture comparison: {englishComparison}");
Console.WriteLine($"French culture comparison: {frenchComparison}");
}
}
4.4.4 - String Interpolation
String interpolation, introduced in C# 6.0, provides a more readable and convenient syntax for creating formatted strings.
4.4.4.1 - Basic String Interpolation
String interpolation uses the $
prefix and curly braces {}
to embed expressions directly in string literals:
Example:
using System;
class Program
{
static void Main()
{
string name = "Alice";
int age = 30;
double height = 1.75;
// Basic string interpolation
string message = $"Name: {name}, Age: {age}, Height: {height}m";
Console.WriteLine(message);
// Expressions in interpolated strings
string complexMessage = $"Name: {name}, Age: {age}, Birth Year: {DateTime.Now.Year - age}";
Console.WriteLine(complexMessage);
// Formatting in interpolated strings
string formattedMessage = $"Name: {name}, Age: {age}, Height: {height:F2}m";
Console.WriteLine(formattedMessage);
// Alignment in interpolated strings
Console.WriteLine($"{"Name",-10} {"Age",5} {"Height",8}");
Console.WriteLine($"{name,-10} {age,5} {height,8:F2}");
}
}
4.4.4.2 - Advanced String Interpolation
String interpolation can be combined with other formatting features:
Example:
using System;
using System.Globalization;
class Program
{
static void Main()
{
double price = 123.45;
DateTime date = DateTime.Now;
// Formatting with different format specifiers
Console.WriteLine($"Price: {price:C}");
Console.WriteLine($"Date: {date:d}");
// Conditional expressions
int score = 85;
Console.WriteLine($"Result: {(score >= 70 ? "Pass" : "Fail")}");
// Verbatim interpolated strings
string path = @"C:\Users\Alice";
Console.WriteLine($@"The path is: {path}\Documents");
// Culture-specific formatting
CultureInfo frenchCulture = CultureInfo.GetCultureInfo("fr-FR");
Console.WriteLine($"French price: {price.ToString("C", frenchCulture)}");
// Interpolated strings with FormattableString
FormattableString fs = $"Price: {price:C}";
Console.WriteLine(fs.ToString(frenchCulture));
// Escaping braces
Console.WriteLine($"To include braces, use double braces: {{ and }}");
}
}
4.4.4.3 - String Interpolation vs. String.Format
String interpolation is a more readable alternative to String.Format
:
Example:
using System;
class Program
{
static void Main()
{
string name = "Alice";
int age = 30;
double height = 1.75;
// Using String.Format
string message1 = string.Format("Name: {0}, Age: {1}, Height: {2:F2}m", name, age, height);
// Using string interpolation
string message2 = $"Name: {name}, Age: {age}, Height: {height:F2}m";
Console.WriteLine("String.Format:");
Console.WriteLine(message1);
Console.WriteLine("\nString Interpolation:");
Console.WriteLine(message2);
// Complex formatting
Console.WriteLine("\nComplex formatting:");
// Using String.Format
string complex1 = string.Format("{0,-10} {1,5} {2,8:F2}", name, age, height);
// Using string interpolation
string complex2 = $"{name,-10} {age,5} {height,8:F2}";
Console.WriteLine("String.Format:");
Console.WriteLine(complex1);
Console.WriteLine("\nString Interpolation:");
Console.WriteLine(complex2);
}
}
4.4.5 - StringBuilder
The StringBuilder
class provides a mutable string-like object that is more efficient for multiple string operations than using the immutable String
class.
4.4.5.1 - Basic StringBuilder Usage
The StringBuilder
class is useful when you need to perform multiple string operations:
Example:
using System;
using System.Text;
class Program
{
static void Main()
{
// Create a StringBuilder
StringBuilder sb = new StringBuilder();
// Append strings
sb.Append("Hello");
sb.Append(", ");
sb.Append("World!");
// Convert to string
string result = sb.ToString();
Console.WriteLine(result);
// Create a StringBuilder with initial content
StringBuilder sb2 = new StringBuilder("Initial text");
Console.WriteLine(sb2.ToString());
// Create a StringBuilder with initial capacity
StringBuilder sb3 = new StringBuilder(50);
sb3.Append("This StringBuilder has an initial capacity of 50 characters.");
Console.WriteLine(sb3.ToString());
}
}
4.4.5.2 - StringBuilder Methods
The StringBuilder
class provides various methods for manipulating strings:
Example:
using System;
using System.Text;
class Program
{
static void Main()
{
StringBuilder sb = new StringBuilder("Hello, World!");
// AppendLine
sb.AppendLine();
sb.AppendLine("This is a new line.");
// Insert
sb.Insert(7, "Beautiful ");
// Remove
sb.Remove(7, 10); // Remove "Beautiful "
// Replace
sb.Replace("World", "C#");
// Clear
StringBuilder sb2 = new StringBuilder("This will be cleared");
sb2.Clear();
sb2.Append("New content after clearing");
// Display results
Console.WriteLine(sb.ToString());
Console.WriteLine(sb2.ToString());
// Append different types
StringBuilder sb3 = new StringBuilder();
sb3.Append("Integer: ");
sb3.Append(42);
sb3.Append(", Double: ");
sb3.Append(3.14159);
sb3.Append(", Boolean: ");
sb3.Append(true);
Console.WriteLine(sb3.ToString());
// AppendFormat
StringBuilder sb4 = new StringBuilder();
sb4.AppendFormat("Name: {0}, Age: {1}", "Alice", 30);
Console.WriteLine(sb4.ToString());
}
}
4.4.5.3 - StringBuilder Properties
The StringBuilder
class has properties that provide information about its state:
Example:
using System;
using System.Text;
class Program
{
static void Main()
{
StringBuilder sb = new StringBuilder("Hello, World!", 50);
// Length property
Console.WriteLine($"Length: {sb.Length}");
// Capacity property
Console.WriteLine($"Capacity: {sb.Capacity}");
// MaxCapacity property
Console.WriteLine($"MaxCapacity: {sb.MaxCapacity}");
// Changing the Length property
sb.Length = 5; // Truncates the string to "Hello"
Console.WriteLine($"After setting Length to 5: '{sb.ToString()}'");
// Changing the Capacity property
sb.Capacity = 100;
Console.WriteLine($"After setting Capacity to 100: {sb.Capacity}");
// Accessing and modifying characters
sb[0] = 'h'; // Change 'H' to 'h'
Console.WriteLine($"After modifying first character: '{sb.ToString()}'");
}
}
4.4.5.4 - StringBuilder vs. String Performance
The StringBuilder
class is more efficient than the String
class for multiple string operations:
Example:
using System;
using System.Diagnostics;
using System.Text;
class Program
{
static void Main()
{
const int iterations = 10000;
// Using String concatenation
Stopwatch sw1 = Stopwatch.StartNew();
string result1 = "";
for (int i = 0; i < iterations; i++)
{
result1 += i.ToString();
}
sw1.Stop();
Console.WriteLine($"String concatenation took {sw1.ElapsedMilliseconds} ms");
Console.WriteLine($"Result length: {result1.Length}");
// Using StringBuilder
Stopwatch sw2 = Stopwatch.StartNew();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < iterations; i++)
{
sb.Append(i);
}
string result2 = sb.ToString();
sw2.Stop();
Console.WriteLine($"StringBuilder took {sw2.ElapsedMilliseconds} ms");
Console.WriteLine($"Result length: {result2.Length}");
}
}
4.4.5.5 - When to Use StringBuilder
Guidelines for when to use StringBuilder
instead of String
:
Example:
using System;
using System.Text;
class Program
{
static void Main()
{
// Scenario 1: Few concatenations - use String
string firstName = "John";
string lastName = "Doe";
string fullName = firstName + " " + lastName;
Console.WriteLine($"Full name: {fullName}");
// Scenario 2: Building a string in a loop - use StringBuilder
StringBuilder emailList = new StringBuilder();
string[] emails = { "john@example.com", "alice@example.com", "bob@example.com" };
emailList.AppendLine("Email List:");
foreach (string email in emails)
{
emailList.AppendLine("- " + email);
}
Console.WriteLine(emailList.ToString());
// Scenario 3: Building a complex string with multiple operations - use StringBuilder
StringBuilder report = new StringBuilder();
report.AppendLine("Monthly Report");
report.AppendLine("=============");
report.AppendLine();
report.AppendLine("Sales:");
report.AppendLine(" Q1: $10,000");
report.AppendLine(" Q2: $15,000");
report.AppendLine(" Q3: $12,000");
report.AppendLine(" Q4: $18,000");
report.AppendLine();
report.AppendLine("Total: $55,000");
Console.WriteLine(report.ToString());
}
}
Working with strings in C# involves a rich set of features for creating, manipulating, formatting, and comparing strings. By understanding these features and knowing when to use the StringBuilder
class for more efficient string operations, you can write more effective and performant code when dealing with text data.