JAL Computing
|
Singleton PatternHere is the ubiquitous Singleton Pattern that restricts the creation to a single instance of a class. This pattern is useful as it:
If you do not need the added level of indirection provided by the Singleton Pattern, it may be simpler to use static methods and fields. You can see the similarities between using the Singleton Pattern and using static methods and fields by comparing the IL generated by similar projects. Both projects create very similar DoIt() stack frames, but the Singleton Pattern adds a pointer to this to the stack frame. Here is the static DoIt() IL: Static : DoIt : void().method private hidebysig static void DoIt() cil managed { // Code size 11 (0xb) .maxstack 1 IL_0000: ldsfld string TestILStatic.Class1::message IL_0005: call void [mscorlib]System.Console::WriteLine(string) IL_000a: ret } // end of method Class1::DoIt Here is the Singleton DoIt() IL: Singleton : DoIt : void().method public hidebysig instance void DoIt() cil managed { // Code size 12 (0xc) .maxstack 1 IL_0000: ldarg.0 IL_0001: ldfld string TestILSingleton.Singleton::message IL_0006: call void [mscorlib]System.Console::WriteLine(string) IL_000b: ret } // end of method Singleton::DoIt Note the added argument on the stack to this. Calling DoIt() in Main is more straightforward in the static approach. Here is the IL from the static project: Static : Main : void(string[]).method private hidebysig static void Main(string[] args) cil managed { .entrypoint .custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 ) // Code size 7 (0x7) .maxstack 0 IL_0000: call void TestILStatic.Class1::DoIt() IL_0005: nop IL_0006: ret } // end of method Class1::Main Now note the added IL instructions using the Singleton Pattern: Singleton : Main : void(string[]).method private hidebysig static void Main(string[] args) cil managed { .entrypoint .custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 ) // Code size 13 (0xd) .maxstack 1 .locals init ([0] class TestILSingleton.Singleton s) IL_0000: call class TestILSingleton.Singleton TestILSingleton.Singleton::GetInstance() IL_0005: stloc.0 IL_0006: ldloc.0 IL_0007: callvirt instance void TestILSingleton.Singleton::DoIt() IL_000c: ret } // end of method Singleton::Main Both approaches produce stack frames for the fields. Here is the static IL: Static : .cctor : void().method private hidebysig specialname rtspecialname static void .cctor() cil managed { // Code size 11 (0xb) .maxstack 1 IL_0000: ldstr "Hello World!" IL_0005: stsfld string TestILStatic.Class1::message IL_000a: ret } // end of method Class1::.cctor Again, the Singleton Pattern generates more complicated IL: Singleton : .ctor : void().method private hidebysig specialname rtspecialname instance void .ctor() cil managed { // Code size 18 (0x12) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldstr "Hello World!" IL_0006: stfld string TestILSingleton.Singleton::message IL_000b: ldarg.0 IL_000c: call instance void [mscorlib]System.Object::.ctor() IL_0011: ret } // end of method Singleton::.ctor By looking at IL generated by the Singleton Pattern and a similar project using static methods and fields, you can see that at the IL level, the code is similar, but more complicated in the project using the Singleton Pattern. The extra complexity of the Singleton Pattern does add a level of indirection. If your project does not make use of this extra level of indirection, you may be able to just use static methods and fields. C# Source Codeusing System; namespace TestILSingleton { class Singleton { private static Singleton s= new Singleton(); static Singleton GetInstance() { return s; } private string message= "Hello World!"; public void DoIt() { System.Console.WriteLine(message); } private Singleton() {;} /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main(string[] args) { // // TODO: Add code to start application here // Singleton s= GetInstance(); s.DoIt(); //System.Console.ReadLine(); } } } Common Intermediate Language Code.class private auto ansi beforefieldinit.class private auto ansi beforefieldinit Singleton extends [mscorlib]System.Object { } // end of class Singleton message : private string.field private string message s : private static class TestILSIngleton.Singleton.field private static class TestILSingleton.Singleton s .cctor : void().method private hidebysig specialname rtspecialname static void .cctor() cil managed { // Code size 11 (0xb) .maxstack 1 IL_0000: newobj instance void TestILSingleton.Singleton::.ctor() IL_0005: stsfld class TestILSingleton.Singleton TestILSingleton.Singleton::s IL_000a: ret } // end of method Singleton::.cctor .ctor : void().method private hidebysig specialname rtspecialname instance void .ctor() cil managed { // Code size 18 (0x12) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldstr "Hello World!" IL_0006: stfld string TestILSingleton.Singleton::message IL_000b: ldarg.0 IL_000c: call instance void [mscorlib]System.Object::.ctor() IL_0011: ret } // end of method Singleton::.ctor DoIt : void().method public hidebysig instance void DoIt() cil managed { // Code size 12 (0xc) .maxstack 1 IL_0000: ldarg.0 IL_0001: ldfld string TestILSingleton.Singleton::message IL_0006: call void [mscorlib]System.Console::WriteLine(string) IL_000b: ret } // end of method Singleton::DoIt GetInstance : class TestILSingleton.Singleton().method private hidebysig static class TestILSingleton.Singleton GetInstance() cil managed { // Code size 10 (0xa) .maxstack 1 .locals init ([0] class TestILSingleton.Singleton CS$00000003$00000000) IL_0000: ldsfld class TestILSingleton.Singleton TestILSingleton.Singleton::s IL_0005: stloc.0 IL_0006: br.s IL_0008 IL_0008: ldloc.0 IL_0009: ret } // end of method Singleton::GetInstance Main : void(string[]).method private hidebysig static void Main(string[] args) cil managed { .entrypoint .custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 ) // Code size 13 (0xd) .maxstack 1 .locals init ([0] class TestILSingleton.Singleton s) IL_0000: call class TestILSingleton.Singleton TestILSingleton.Singleton::GetInstance() IL_0005: stloc.0 IL_0006: ldloc.0 IL_0007: callvirt instance void TestILSingleton.Singleton::DoIt() IL_000c: ret } // end of method Singleton::Main |
Send mail to [email protected]
with questions or comments about this web site. Copyright © 2001, 2002, 2003,
2004, 2005, 2006, 2007, 2008, 2009 ©
|