C-Sharp | Java | Python | Swift | GO | WPF | Ruby | Scala | F# | JavaScript | SQL | PHP | Angular | HTML
Note: The string pool is an optimization mainly for string literals, which are strings that you place directly in your code.
Literals: String literals are surrounded by quotes. They are constant and immutable—meaning you can't change them.
String LiteralC# program that uses string.Intern
class Program
{
static void Main()
{
// Regular string literal.
string s1 = "I'm a string literal.";
// Const string literal.
const string s2 = "I'm also a string literal.";
// Verbatim string literal.
string s3 = @"I'm a string literal
with the verbatim syntax.";
}
}
Here: In this program, we modify a string reference only. The actual data, the literals, are left alone.
C# program that reassigns string literals
class Program
{
static void Main()
{
string s = "I'm a string literal.";
s = "I'm another literal.";
}
}
Part A: This string is generated at runtime, so it is not from the internal string pool. It is on the heap.
Part B: We take the string created at runtime, and add it to the string pool. Now it is similar to a string literal.
C# program that in terns string
using System.Text;
class Program
{
static void Main()
{
// Part A: create string at runtime.
string s1 = new StringBuilder().Append("cat").Append(" and dog").ToString();
// Part B: get interned string added at runtime.
string s2 = string.Intern(s1);
}
}
Next: The Equals method is how the == operator is implemented in the .NET Framework. The first part tests the references for equality.
Also: EqualsHelper compares all the characters in a loop and is slower. It is called if the other conditions do not short-circuit.
Implementation of string.Equals: C#
public static bool Equals(string a, string b)
{
return ((a == b) || (((a != null) && (b != null)) && EqualsHelper(a, b)));
}
Version 1: In this version of the code, we compare string literals against a string that has not been interned.
Version 2: Here we test string literals against a string that had string.Intern called upon it. We use interned strings.
Result: String.Intern improves performance by more than 4 times when the string comparison is always true.
Info: The string.Intern method only speeds things up when 2 strings are equal, and both are interned.
C# program that benchmarks string.Intern tests
using System;
using System.Text;
class Program
{
static void Main()
{
// Create string at runtime.
StringBuilder b = new StringBuilder().Append("cat ").Append(
"and ").Append("dog");
// Get runtime string.
string s1 = b.ToString();
// Get string pool reference to string.
string s2 = string.Intern(s1);
int m = 10000;
for (int v = 0; v < 10; v++)
{
int d = 0;
long t1 = Environment.TickCount;
// Version 1: test regular string.
for (int i = 0; i < m; i++)
{
for (int a = 0; a < m; a++)
{
if (s1 == "cat and rabbit")
{
d++; // false
}
if (s1 == "cat and dog")
{
d--; // true
}
}
}
long t2 = Environment.TickCount;
// Version 2: test interned string.
for (int i = 0; i < m; i++)
{
for (int a = 0; a < m; a++)
{
if (s2 == "cat and rabbit")
{
d++; // false
}
if (s2 == "cat and dog")
{
d--; // true
}
}
}
// Write results.
long t3 = Environment.TickCount;
Console.Write((t2 - t1));
Console.WriteLine("," + (t3 - t2));
}
Console.ReadLine();
}
}
Output
No string.Intern: 1540 ms
With string.Intern: 736 ms [faster]
Info: If the internal string is found, that reference is returned. If no internal string is present, a null reference is returned.
NullFirst: A string literal is tested. This reveals that string literals are always present in the intern table.
And: On the other hand, a dynamically constructed string is not present in the intern table.
Null: IsInterned will return null in this case. It will not add the string to the intern table.
C# program that uses IsInterned method
using System;
class Program
{
static void Main()
{
// See if a string literal is interned.
string value1 = "cat";
string value2 = string.IsInterned(value1);
Console.WriteLine(value2);
// See if a dynamically constructed string is interned.
string value3 = "cat" + 1.ToString();
string value4 = string.IsInterned(value3);
Console.WriteLine(value4 == null);
}
}
Output
cat
True