Singleton mode is one of the most common design patterns, and we often write such code. Because the basic principle is to save a static object instance, we can use generics to write out a generic singleton class.
 
The code is simple:
 
public class Singleton<T>
   ...{
     static readonly T _t;
     static Singleton()
     ...{
       _t = Construct();
     }
     public static T GetInstance()
     ...{
       return _t;
     }
     private static T Construct()
     ...{
       Type type = typeof(T);
       ConstructorInfo ctor;
       ctor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
                     null, new Type[0], new ParameterModifier[0]);
       System.Diagnostics.Debug.Assert(ctor != null, "Error in ENLS.Basic.Singleton.Construct().");
       return (T)ctor.Invoke(new object[0]);
     }
   }
 
Because the special generic classes are different types,singleton<tuple<int>> and singleton<tuple<int,long>> are different, so the _ in these two classes T is a different static instance. Then the new instance is created by invoking a common or private default constructor parameter in the construct method. Why is there a public constructor? This is to use the Nullobject mode. For example, for the sake of convenience, I want to add a method to the tuple base class to the Null object
 
public static Tuple GetNullInstance<_Tuple>() where _Tuple: Tuple
 {
    return Singleton<_Tuple>.GetInstance();
 }With this empty object, I can simply use the function that iterates through the control described in the previous article.
 
public IEnumerable<Control> Iterator<_Tuple>(Control baseCtl) where _Tuple : Tuple
     ...{
       Tuple tuple = Tuple.GetNullInstance<_Tuple>();
       foreach(Control c in baseCtl.Controls)
       ...{
         if (!tuple.HasType(c))
         ...{
           foreach (Control c1 in Iterator<_Tuple>(c))
             yield return c1;
         }
         else
           yield return c;
       }
     }
 
This makes it easy to call the
 
foreach (Control c in this.Iterator<Tuple<TextBox, TreeView, CheckBox>>(this))
         MessageBox.Show(c.Name);