Skip to content

Strings

↑
Data structures

A string represents text as an ordered sequence of characters. In C#, a string is immutable, which means methods that appear to edit it usually return a new string instead of modifying the original.

Try it yourself

A C# string is immutable. This example shows character indexes.

A C# string is immutable. This example shows character indexes.

Select a character to see its index. The string remains unchanged.

C# | Strings.cs
string name = "HELLO";
Console.WriteLine(name.Length); // 5 UTF-16 code units
Console.WriteLine(name[1]); // E
string result = name.Replace("L", "R");
Console.WriteLine(name); // Still HELLO

Repeatedly concatenating strings inside a large loop can create many intermediate string objects. When building text incrementally in C#, StringBuilder is often a better fit.

C# | StringBuilder.cs
var builder = new System.Text.StringBuilder();
foreach (string word in words)
builder.Append(word);
string sentence = builder.ToString();
Action Typical complexity
Read a UTF-16 code unit by index O(1)
Traverse all code units O(n)
Search for a substring Depends on algorithm and implementation
Concatenate two strings O(n + m) to copy the data

Text is more than an array of visible letters

Section titled “Text is more than an array of visible letters”

Unicode contains characters represented by one or more code points, and some visible graphemes consist of several code points. In .NET, string.Length counts UTF-16 code units, not necessarily characters perceived by a reader. In C++, std::string::size() counts bytes. Neither measurement alone is reliable for counting user-visible symbols.

Text comparisons depend on whether your application wants ordinal, case-insensitive or culture-sensitive behavior. Use explicit comparison rules for identifiers, filenames and user-facing search. Unicode normalization can matter when visually identical strings have different underlying encodings.

Repeated string concatenation in a loop can create many temporary immutable string values. In C#, StringBuilder can reduce allocations for a growing result. In C++, pre-reserving capacity in std::string can help when an approximate final size is known.