C# String Pooling
C# uses a concept called string pooling, where all literal strings are stored in a pool to reduce memory usage. When a literal string is used multiple times, C# reuses the same string from the pool instead of creating new instances. This mechanism optimizes memory usage and improves performance by avoiding the creation of redundant string objects.
Key Topics
1. String Pooling Concept
String pooling is an optimization technique used by the Common Language Runtime (CLR) to store only one instance of each unique literal string in a special memory area called the intern pool. When the same string literal appears multiple times in the code, the CLR reuses the existing instance from the pool instead of creating a new one.
Example: Basic String Pooling
string str1 = "Hello";
string str2 = "Hello";
Console.WriteLine(object.ReferenceEquals(str1, str2)); // Outputs: True
Output:
Code Explanation: Both str1
and str2
reference the same string instance in the intern pool, resulting in True
when compared using ReferenceEquals()
.
2. Reference Equality of Literals
When string literals with the same value are declared, they point to the same memory location in the intern pool, ensuring reference equality.
Example: Comparing String Literals
string str1 = "Hello";
string str2 = "Hello";
Console.WriteLine(object.ReferenceEquals(str1, str2)); // Outputs: True
3. Runtime Strings and Interning
Strings created at runtime (not as literals) are not automatically interned. However, you can manually intern them using the String.Intern()
method.
Example: Runtime String Interning
string str1 = new string(new char[] { 'H', 'e', 'l', 'l', 'o' });
string str2 = String.Intern(str1);
string str3 = "Hello";
Console.WriteLine(object.ReferenceEquals(str2, str3)); // Outputs: True
Output:
Code Explanation: The runtime-created string str1
is interned using String.Intern()
, making it reference the same instance as the literal string str3
, resulting in True
when compared using ReferenceEquals()
.
4. Memory Efficiency
String pooling enhances memory efficiency by ensuring that identical strings share the same memory space, reducing the overall memory footprint of the application.
Example: Memory Usage Comparison
string[] literals = new string[1000];
string[] runtimeStrings = new string[1000];
for(int i = 0; i < 1000; i++)
{
literals[i] = "Test"; // Interned
runtimeStrings[i] = new string(new char[] { 'T', 'e', 's', 't' }); // Not interned
}
int internedReferences = 0;
for(int i = 0; i < 1000; i++)
{
if(object.ReferenceEquals(literals[i], literals[0]))
internedReferences++;
}
int nonInternedReferences = 0;
for(int i = 0; i < 1000; i++)
{
if(object.ReferenceEquals(runtimeStrings[i], runtimeStrings[0]))
nonInternedReferences++;
}
Console.WriteLine($"Interned References: {internedReferences}"); // Outputs: Interned References: 1000
Console.WriteLine($"Non-Interned References: {nonInternedReferences}"); // Outputs: Non-Interned References: 1
Output:
Non-Interned References: 1
Code Explanation: The first loop initializes two arrays of strings: literals
with string literals and runtimeStrings
with runtime-created strings. The second loop checks reference equality for interned literals, which all point to the same instance, resulting in 1000
matches. The third loop checks reference equality for runtime strings, which are unique, resulting in only 1
match.
5. Using String.Intern()
Method
The String.Intern()
method can be used to intern runtime-created strings manually, ensuring that they reference the same instance in the intern pool if they have identical values.
Example: Manual String Interning
string runtimeStr = new string(new char[] { 'C', '#', ' ', 'I', 's', ' ', 'F', 'u', 'n' });
string internedStr = String.Intern(runtimeStr);
string literalStr = "C# Is Fun";
Console.WriteLine(object.ReferenceEquals(internedStr, literalStr)); // Outputs: True
Output:
Code Explanation: The runtime-created string runtimeStr
is interned using String.Intern()
, making it reference the same instance as the literal string literalStr
, resulting in True
when compared using ReferenceEquals()
.
Key Takeaways
- String pooling is an automatic feature in C# that optimizes memory usage by reusing string instances.
- String literals with the same value share the same reference in the intern pool.
- Runtime-created strings are not interned by default but can be manually interned using
String.Intern()
. - String pooling reduces memory usage and improves performance by avoiding duplicate string instances.
- Understanding string pooling helps in writing memory-efficient and high-performance code.