C-Sharp | Java | Python | Swift | GO | WPF | Ruby | Scala | F# | JavaScript | SQL | PHP | Angular | HTML
SiteStructure: The readonly and static keywords are critical here. Readonly allows thread-safety, and that means it can be only allocated once.
Info: The public Instance property is used by callers to get the singleton instance.
ReadonlyPropertyC# program that uses singleton
class Program
{
static void Main()
{
SiteStructure s = SiteStructure.Instance;
}
}
public sealed class SiteStructure
{
static readonly SiteStructure _instance = new SiteStructure();
public static SiteStructure Instance
{
get
{
return _instance;
}
}
SiteStructure()
{
// Initialize.
}
}
Also: They cause problems. They are lazily instantiated. Every access to the class must check that the static constructor has run.
StaticHowever: My testing shows that by exchanging the property for a public field, the benchmark is sped up.
C# program that uses public field, singleton
using System;
class SingletonB
{
public static readonly SingletonB _instance = new SingletonB();
public void Test()
{
// Code runs.
Console.WriteLine(true);
}
SingletonB()
{
}
}
class Program
{
public static void Main()
{
SingletonB._instance.Test();
}
}
Output
True
Result: In one million iterations of the Test function in the above version, the program completed in 1.935 seconds. That is efficient.
Note: The public field is over 10% faster. I recommend skipping the public property as shown first and simply using the field.
Singleton benchmark: 2
Singleton: Property
Time: 1.935 s
Singleton: Public field
Time: 1.731 s
Therefore: Accessing a singleton always incurs a performance hit when first called in a method.
MSIL code for singleton
L_0000: ldsfld class Perls.Metadata Perls.Metadata::Instance
L_0005: ldarg.0
L_0006: ldloca.s data
L_0008: callvirt instance bool Perls.Metadata::TryGetFile(string,
class Perls.FileData&)
MSIL code for static class
L_0000: ldarg.0
L_0001: ldloca.s data
L_0003: call bool Perls.Metadata::TryGetFile(string, class Perls.FileData&)
Also: The callvirt is replaced with a call opcode. This also improves performance.