C# 一般的单例
你们对一般的单身汉怎么看C# 一般的单例,c#,singleton,generics,C#,Singleton,Generics,你们对一般的单身汉怎么看 using System; using System.Reflection; // Use like this /* public class Highlander : Singleton<Highlander> { private Highlander() { Console.WriteLine("There can be only one..."); } } */ public class Singleton&
using System;
using System.Reflection;
// Use like this
/*
public class Highlander : Singleton<Highlander>
{
private Highlander()
{
Console.WriteLine("There can be only one...");
}
}
*/
public class Singleton<T> where T : class
{
private static T instance;
private static object initLock = new object();
public static T GetInstance()
{
if (instance == null)
{
CreateInstance();
}
return instance;
}
private static void CreateInstance()
{
lock (initLock)
{
if (instance == null)
{
Type t = typeof(T);
// Ensure there are no public constructors...
ConstructorInfo[] ctors = t.GetConstructors();
if (ctors.Length > 0)
{
throw new InvalidOperationException(String.Format("{0} has at least one accesible ctor making it impossible to enforce singleton behaviour", t.Name));
}
// Create an instance via the private constructor
instance = (T)Activator.CreateInstance(t, true);
}
}
}
}
使用系统;
运用系统反思;
//像这样使用
/*
公务舱高地人:单身汉
{
私人高地人()
{
Console.WriteLine(“只能有一个…”);
}
}
*/
公共类单例,其中T:class
{
私有静态T实例;
私有静态对象initLock=新对象();
公共静态GetInstance()
{
if(实例==null)
{
CreateInstance();
}
返回实例;
}
私有静态void CreateInstance()
{
锁(initLock)
{
if(实例==null)
{
类型t=类型(t);
//确保没有公共构造函数。。。
ConstructorInfo[]ctors=t.GetConstructors();
如果(ctors.Length>0)
{
抛出新的InvalidOperationException(String.Format(“{0}至少有一个可访问的构造函数,使得无法强制执行单例行为”,t.Name));
}
//通过私有构造函数创建实例
instance=(T)Activator.CreateInstance(T,true);
}
}
}
}
好吧,它不是真正的单例-因为您无法控制t
,所以可以有任意多个t
实例
(删除了线程争用;注意了双重检查的用法)创建一个单例类只需要几行代码,而且由于创建通用单例的困难,我总是编写这些代码行
public class Singleton
{
private Singleton() {}
static Singleton() {}
private static Singleton _instance = new Singleton();
public static Singleton Instance { get { return _instance; }}
}
行消除了锁定的需要,因为静态构造函数是线程安全的。我删除了我以前的答案,因为我没有注意到检查非公共构造函数的代码。然而,这是一个只在执行时执行的检查——没有编译时检查,这是对它的攻击。它还依赖于拥有足够的访问权限来调用非公共构造函数,这增加了一些限制 此外,它并不禁止内部构造函数-因此您可以使用非单例 我个人也会在静态构造函数中创建实例,以实现简单的线程安全
基本上,我不太喜欢创建单例类——创建单例类非常容易,无论如何,你不应该经常这样做。对于测试、解耦等来说,单例是一种痛苦。这是我使用.NET4的观点
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; } }
}
公共类单例,其中T:class,new()
{
单态(){}
私有静态只读惰性实例=newlazy(()=>newt());
公共静态T实例{get{return Instance.Value;}}
}
它的用途如下:
public class Adaptor
{
public static Adaptor Instance { get { return Singleton<Adaptor>.Instance;}}
}
公共类适配器
{
公共静态适配器实例{get{return Singleton.Instance;}}
}
融合AndreasN answer和Jon Skeet的“单例c#实现”,为什么不使用代码片段来完成所有的艰苦工作:
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<Title>Singleton Class</Title>
<Author>TWSoft</Author>
<Description>Generates a singleton class</Description>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
</SnippetTypes>
<Keywords>
<Keyword>Singleton</Keyword>
</Keywords>
<Shortcut>singleton</Shortcut>
</Header>
<Snippet>
<Declarations>
<Literal>
<ID>ClassName</ID>
<ToolTip>Replace with class name</ToolTip>
<Default>MySingletonClass</Default>
</Literal>
</Declarations>
<Code Language="CSharp">
<![CDATA[
public class $ClassName$
{
#region Singleton
static readonly $ClassName$ mInstance = new $ClassName$();
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static $ClassName$()
{
}
private $ClassName$()
{
}
public static $ClassName$ Instance
{
get { return mInstance; }
}
#endregion
}
]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>
独生子女班
TWSoft
生成一个单例类
膨胀
独生子女
独生子女
类名
替换为类名
MySingletonClass
然后您可以将其保存到.snippt文件中,并将其添加到VS IDE(工具->代码片段管理器)使用泛型对单例无效。因为您总是可以创建类型参数T的多个实例,然后根据定义,它是而不是 看看这个:
public sealed class Singleton<T> where T : class, new()
{
private static readonly Lazy<T> instance = new Lazy<T>(() => new T());
public static T Instance => instance.Value;
private Singleton() { }
}
将私有构造函数添加到适配器会破坏代码。
请注意,此适配器使用组合而不是继承。也就是说,它不是一个单身汉,它有一个单身汉。如果某个东西是单例的,它应该派生或实现一个接口
public abstract class Singleton<T>
{
protected static Lazy<T> instance;
public static T Instance => instance.Value;
}
public sealed class Adapter : Singleton<Adapter>
{
static Adapter()
{
instance = new Lazy<Adapter>(() => new Adapter());
}
private Adapter() { }
}
也
此类错误只能在测试期间检测到
我仍然更愿意直接使用模式,它基本上只有3行代码,而且编译时是安全的。另外,当您需要不同的基类,但仍然需要一个懒惰的单例,并要求它是一个真正的单例时,存在一个简单的解决方案:(请参阅:)
公共密封类适配器
{
私有静态只读惰性实例=新惰性(()=>新适配器());
公共静态适配器实例{get{return Instance.Value;}}
专用适配器(){}
}
您无法将其正确地重构为一个通用的单例,不能像上面研究的方法那样被误用。完全正确。特别是当泛型版本实际上并没有给你一个单例时……你可能还应该添加一个静态构造函数。确实看到了。对于延迟加载,Jon的页面也用嵌套类覆盖了这一点。除非对锁定对象使用volatile关键字,否则这种锁定技术将被破坏。参见我在链接的Jon Skeet文章中添加了静态构造函数;在大多数情况下,静态类更合适。用于实现接口等,但标准模式工作良好,无需泛型。不要忘记链接…Jon!:)@肯尼:那个链接正是我需要的。谢谢除非对锁定对象使用volatile关键字,否则此锁定技术将被破坏。请参阅codereview.stackexchange.com的精细问题此方法的问题是它需要singleton实现类的公共构造函数,这允许在singleton实例的边界之外使用(即,这里不存在编译时预防)。这是其泛型的成本。是的,只是需要让noob明白,你应该给适配器添加一个私有构造函数,这会破坏你的设计。这是它的泛型的成本
public class Adapter
{
public static Adapter Instance => Singleton<Adapter>.Instance;
// private Adapter(){ } // doesn't compile.
}
new Adapter();
public abstract class Singleton<T>
{
protected static Lazy<T> instance;
public static T Instance => instance.Value;
}
public sealed class Adapter : Singleton<Adapter>
{
static Adapter()
{
instance = new Lazy<Adapter>(() => new Adapter());
}
private Adapter() { }
}
public abstract class Singleton<T> where T : Singleton<T>, new()
{
private static bool instantiated;
private static readonly Lazy<T> instance = new Lazy<T>(() => new T());
public static T Instance => instance.Value;
protected Singleton()
{
if (instantiated)
throw new Exception();
instantiated = true;
}
}
public /* sealed */ class Adapter : Singleton<Adapter>
{
}
new Adapter(); // this works
Adapter.Instance; // this throws an error.
Adapter.Instance; // this works
// just running in production someone decided to call:
new Adapter(); // this throws an error
public sealed class Adapter
{
private static readonly Lazy<Adapter> instance = new Lazy<Adapter>(() => new Adapter());
public static Adapter Instance { get { return instance.Value; } }
private Adapter() { }
}