Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 什么';在C语言中,这是一个很好的线程安全单例通用模板模式#_C#_Design Patterns - Fatal编程技术网

C# 什么';在C语言中,这是一个很好的线程安全单例通用模板模式#

C# 什么';在C语言中,这是一个很好的线程安全单例通用模板模式#,c#,design-patterns,C#,Design Patterns,我有下面的C#singleton模式,有什么改进的方法吗 public class Singleton<T> where T : class, new() { private static object _syncobj = new object(); private static volatile T _instance = null; public static T Instance {

我有下面的C#singleton模式,有什么改进的方法吗

    public class Singleton<T> where T : class, new()
    {

        private static object _syncobj = new object();
        private static volatile T _instance = null;
        public static T Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (_syncobj)
                    {
                        if (_instance == null)
                        {
                            _instance = new T();
                        }
                    }
                }
                return _instance;
            }
        }

        public Singleton()
        { }

    }
公共类单例,其中T:class,new()
{
私有静态对象_syncobj=新对象();
私有静态volatile T_实例=null;
公共静态T实例
{
得到
{
if(_instance==null)
{
锁定(_syncobj)
{
if(_instance==null)
{
_实例=新的T();
}
}
}
返回_实例;
}
}
公共单身人士()
{ }
}
首选用法示例:

class Foo : Singleton<Foo> 
{
} 
类Foo:Singleton
{
} 
相关的


朱迪思·毕肖普提供

这种单例模式实现确保了延迟初始化

//  Singleton PatternJudith Bishop Nov 2007
//  Generic version

public class Singleton<T> where T : class, new()
{
    Singleton() { }

    class SingletonCreator
    {
        static SingletonCreator() { }
        // Private object instantiated with private constructor
        internal static readonly T instance = new T();
    }

    public static T UniqueInstance
    {
        get { return SingletonCreator.instance; }
    }
}
//单身模式Judith Bishop 2007年11月
//通用版本
公共类单例,其中T:class,new()
{
Singleton(){}
类单音创建者
{
静态SingletonCreator(){}
//使用私有构造函数实例化的私有对象
内部静态只读T实例=新T();
}
公共静态T唯一实例
{
获取{return SingletonCreator.instance;}
}
}
有一个;但这会引发线程问题。

根据Jon Skeet的说法,您发布的代码实际上被视为坏代码,因为在对照ECMA CLI标准进行检查时,它看起来是坏代码


还要注意:每次你用一个新类型的T实例化你的对象,它就会变成另一个实例;它没有反映在您最初的单例中。

我很喜欢您最初的答案-唯一缺少的东西(根据blowdart发布的链接)是使_实例变量不稳定,以确保它实际上已在锁中设置。 实际上,当我必须使用单例时,我会使用blowdarts解决方案,但我不需要延迟实例化等。

你不需要所有这些,C#已经内置了一个很好的单例模式

static class Foo
如果您需要比这更有趣的东西,那么您的新单例很可能会变得完全不同,以至于您的通用模式将毫无用处


编辑:通过“任何更有趣的东西”,我包括了继承。如果您可以从单例继承,那么它就不再是单例。

此代码不会编译,您需要对t进行“类”约束

此外,这段代码需要目标类上的公共构造函数,这对singleton不好,因为您无法在编译时控制仅通过实例属性(或字段)获取(单个)实例。如果除Instance之外没有任何其他静态成员,则可以只使用以下内容:

class Foo
{
  public static readonly Instance = new Foo();
  private Foo() {}
  static Foo() {}
}
它是线程安全的(由CLR保证)和惰性的(实例是通过对类型的第一次访问创建的)。有关BeforeFieldInit以及为什么需要静态构造函数的更多讨论,请参阅


如果您希望在类型上有其他公共静态成员,但仅在访问实例时创建对象,则可以创建嵌套类型,如

中所述。我认为您并不是真的希望“烧掉基类”,以便可以保存两行代码。实现singleton实际上不需要基类

无论何时,只要您需要单身,就可以这样做:

class MyConcreteClass
{
  #region Singleton Implementation

    public static readonly Instance = new MyConcreteClass();

    private MyConcreteClass(){}

  #endregion

    /// ...
}

有关此答案的更多详细信息,请参阅其他线程:


然而,线程没有使用泛型

我正在寻找一个更好的单例模式,并且喜欢这个模式。因此,将其移植到VB.NET,可能对其他人有用:

Public MustInherit Class Singleton(Of T As {Class, New})
    Public Sub New()
    End Sub

    Private Class SingletonCreator
        Shared Sub New()
        End Sub
        Friend Shared ReadOnly Instance As New T
    End Class

    Public Shared ReadOnly Property Instance() As T
        Get
            Return SingletonCreator.Instance
        End Get
    End Property
End Class

我对确保按需创建实例数据的贡献:


/// <summary>Abstract base class for thread-safe singleton objects</summary>
/// <typeparam name="T">Instance type</typeparam>
public abstract class SingletonOnDemand<T> {
    private static object __SYNC = new object();
    private static volatile bool _IsInstanceCreated = false;
    private static T _Instance = default(T);

/// <summary>Instance data</summary> public static T Instance { get { if (!_IsInstanceCreated) lock (__SYNC) if (!_IsInstanceCreated) _Instance = Activator.CreateInstance<T>(); return _Instance; } } }

/// <summary>Abstract base class for thread-safe singleton objects</summary>
/// <typeparam name="T">Instance type</typeparam>
public abstract class SingletonOnDemand<T> {
  private static object __SYNC = new object();
  private static volatile bool _IsInstanceCreated = false;
  private static T _Instance = default(T);

  /// <summary>Instance data</summary>
  public static T Instance {
    get {
      if (!_IsInstanceCreated)
        lock (__SYNC)
          if (!_IsInstanceCreated) {
            _Instance = Activator.CreateInstance<T>();
            _IsInstanceCreated = true;
          }
          return _Instance;
    }
  }
}

///线程安全单例对象的抽象基类
///实例类型
公共抽象类SingletonOnDemand{
私有静态对象_SYNC=新对象();
私有静态易失性bool _IsInstanceCreated=false;
私有静态T_实例=默认值(T);

///实例数据 公共静态T实例{ 得到{ 如果(!\u已创建安装) 锁定(同步) 如果(!\u已创建安装) _Instance=Activator.CreateInstance(); 返回_实例; } } }
pff。。。再次…:)
我对确保按需创建实例数据的贡献:


/// <summary>Abstract base class for thread-safe singleton objects</summary>
/// <typeparam name="T">Instance type</typeparam>
public abstract class SingletonOnDemand<T> {
    private static object __SYNC = new object();
    private static volatile bool _IsInstanceCreated = false;
    private static T _Instance = default(T);

/// <summary>Instance data</summary> public static T Instance { get { if (!_IsInstanceCreated) lock (__SYNC) if (!_IsInstanceCreated) _Instance = Activator.CreateInstance<T>(); return _Instance; } } }

/// <summary>Abstract base class for thread-safe singleton objects</summary>
/// <typeparam name="T">Instance type</typeparam>
public abstract class SingletonOnDemand<T> {
  private static object __SYNC = new object();
  private static volatile bool _IsInstanceCreated = false;
  private static T _Instance = default(T);

  /// <summary>Instance data</summary>
  public static T Instance {
    get {
      if (!_IsInstanceCreated)
        lock (__SYNC)
          if (!_IsInstanceCreated) {
            _Instance = Activator.CreateInstance<T>();
            _IsInstanceCreated = true;
          }
          return _Instance;
    }
  }
}

///线程安全单例对象的抽象基类
///实例类型
公共抽象类SingletonOnDemand{
私有静态对象_SYNC=新对象();
私有静态易失性bool _IsInstanceCreated=false;
私有静态T_实例=默认值(T);
///实例数据
公共静态T实例{
得到{
如果(!\u已创建安装)
锁定(同步)
如果(!\u已创建安装){
_Instance=Activator.CreateInstance();
_IsInstanceCreated=true;
}
返回_实例;
}
}
}

根据要求,将我的原始答案交叉张贴到另一个问题上

我的版本使用反射,与派生类中的非公共构造函数一起工作,是线程安全的(显然)惰性实例化(根据我在下面链接的文章):

公共类SingletonBase,其中T:class
{
静态单碱基()
{
}
公共静态只读T实例=
typeof(T).InvokeMember(typeof(T).Name,
BindingFlags.CreateInstance|
BindingFlags.Instance|
BindingFlags.Public|
BindingFlags.NonPublic,
null,null,null)作为T;
}
我在几年前就知道了,不知道有多少是我的,但是如果不是我的话,在代码上搜索可能会找到技术的原始来源

这是第一次,但不是
public sealed class Singleton
{
  private static readonly Singleton _instance = new Singleton();

  private Singleton()
  {
  }

  public static Singleton Instance
  {
    get
    {
      return _instance;
    }
  }
}
public static class LazyGlobal<T> where T : new()
{
    public static T Instance
    {
        get { return TType.Instance; }
    }

    private static class TType
    {
        public static readonly T Instance = new T();
    }
}

// user code:
{
    LazyGlobal<Foo>.Instance.Bar();
}
public delegate T Func<T>();

public static class CustomGlobalActivator<T>
{
    public static Func<T> CreateInstance { get; set; }
}

public static class LazyGlobal<T>
{
    public static T Instance
    {
        get { return TType.Instance; }
    }

    private static class TType
    {
        public static readonly T Instance = CustomGlobalActivator<T>.CreateInstance();
    }
}

{
    // setup code:
    // CustomGlobalActivator<Foo>.CreateInstance = () => new Foo(instanceOf_SL_or_IoC.DoSomeMagicReturning<FooDependencies>());
    CustomGlobalActivator<Foo>.CreateInstance = () => instanceOf_SL_or_IoC.PleaseResolve<Foo>();
    // ...
    // user code:
    LazyGlobal<Foo>.Instance.Bar();
}
public static class Singleton<T>
{
    private static object lockVar = new object();
    private static bool made;
    private static T _singleton = default(T);

    /// <summary>
    /// Get The Singleton
    /// </summary>
    public static T Get
    {
        get
        {
            if (!made)
            {
                lock (lockVar)
                {
                    if (!made)
                    {
                        ConstructorInfo cInfo = typeof(T).GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[0], null);
                        if (cInfo != null)
                            _singleton = (T)cInfo.Invoke(new object[0]);
                        else
                            throw new ArgumentException("Type Does Not Have A Default Constructor.");
                        made = true;
                    }
                }
            }

            return _singleton;
        }
    }
}
public abstract class Singleton<T> where T : class
{
    /// <summary>
    /// Returns the singleton instance.
    /// </summary>
    public static T Instance
    {
        get
        {
            return SingletonAllocator.instance;
        }
    }

    internal static class SingletonAllocator
    {
        internal static T instance;

        static SingletonAllocator()
        {
            CreateInstance(typeof(T));
        }

        public static T CreateInstance(Type type)
        {
            ConstructorInfo[] ctorsPublic = type.GetConstructors(
                BindingFlags.Instance | BindingFlags.Public);

            if (ctorsPublic.Length > 0)
                throw new Exception(
                    type.FullName + " has one or more public constructors so the property cannot be enforced.");

            ConstructorInfo ctorNonPublic = type.GetConstructor(
                BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[0], new ParameterModifier[0]);

            if (ctorNonPublic == null)
            {
                throw new Exception(
                    type.FullName + " doesn't have a private/protected constructor so the property cannot be enforced.");
            }

            try
            {
                return instance = (T)ctorNonPublic.Invoke(new object[0]);
            }
            catch (Exception e)
            {
                throw new Exception(
                    "The Singleton couldnt be constructed, check if " + type.FullName + " has a default constructor", e);
            }
        }
    }
}
public sealed class Singleton
{ 
   private Singleton() { }

   public static Singleton Instance
   {
      get
      {
         return SingletonCreator.instance;
      }
   }

   private class SingletonCreator
   {
      static SingletonCreator() { }
      internal static readonly Singleton instance = new Singleton();
   }
}
Singleton s1 = Singleton.Instance;
Singleton s2 = Singleton.Instance;
if (s1.Equals(s2))
{
    Console.WriteLine("Thread-Safe Singleton objects are the same");
}
public class Singleton<T>
    where T : class, new()
{
    private Singleton() { }

    public static T Instance 
    { 
        get 
        { 
            return SingletonCreator.instance; 
        } 
    } 

    private class SingletonCreator 
    {
        static SingletonCreator() { }

        internal static readonly T instance = new T();
    }
}
class TestClass { }

Singleton s1 = Singleton<TestClass>.Instance;
Singleton s2 = Singleton<TestClass>.Instance;
if (s1.Equals(s2))
{
    Console.WriteLine("Thread-Safe Generic Singleton objects are the same");
}
using System.Runtime.CompilerServices;
[MethodImpl (MethodImplOptions.Synchronized)]
public static void MySynchronizedMethod()
{
}
public class Singleton<T> where T : class
{
    class SingletonCreator
    {
        static SingletonCreator() { }

        internal static readonly T Instance =
            typeof(T).InvokeMember(typeof(T).Name,
                                    BindingFlags.CreateInstance |
                                    BindingFlags.Instance |
                                    BindingFlags.Public |
                                    BindingFlags.NonPublic,
                                    null, null, null) as T;
    }

    public static T Instance
    {
        get { return SingletonCreator.Instance; }
    }
}
public class Foo: Singleton<Foo>
{
     private Foo() { }
}
Foo.Instance.SomeMethod();
public class Singleton<T> where T : class, new()
    {
        Singleton (){}

        private static readonly Lazy<T> instance = new Lazy<T>(()=> new T());

        public static T Instance { get { return instance.Value; } } 
    }
public class MyClass
{
        private MyClass()
        {

        }

        static MyClass()
        {
            Instance = new MyClass();
        }

        public static MyClass Instance { get; private set; }
}
public class MyClass
    {
            private MyClass()
            {

            }

            static MyClass()
            {
                Instance = new MyClass();
            }

            private static MyClass instance;



            public static MyClass Instance
            {
                get
                {
                    return instance;
                }
                private set
                {
                    instance = value;
                }
            }
    }
public static class Singleton<T> 
{
    private static readonly object Sync = new object();

    public static T GetSingleton(ref T singletonMember, Func<T> initializer)
    {
        if (singletonMember == null)
        {
            lock (Sync)
            {
                if (singletonMember == null)
                    singletonMember = initializer();
            }
        }
        return singletonMember;
    }
}
private static MyType _current;
public static MyType Current = Singleton<MyType>.GetSingleton(ref _current, () => new MyType());
MyType.Current. ...
 private Singleton ()
        {
            Console.WriteLine("usage of the Singleton for the first time");
        }
Parallel.For(0, 10,
              index => {
                  Thread tt = new Thread(new ThreadStart(Singleton.Instance.SomePrintMethod));
                  tt.Start();
              });