什么是 C# 中好的线程安全单例通用模板模式
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/100081/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What's a good threadsafe singleton generic template pattern in C#
提问by Sam Saffron
I have the following C# singleton pattern, is there any way of improving it?
我有以下 C# 单例模式,有什么改进的方法吗?
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()
{ }
}
Preferred usage example:
首选用法示例:
class Foo : Singleton<Foo>
{
}
Related:
相关:
回答by EggyBach
Courtesy of Judith Bishop, http://patterns.cs.up.ac.za/
由 Judith Bishop 提供,http://patterns.cs.up.ac.za/
This singleton pattern implementation ensures lazy initialisation.
这种单例模式实现可确保延迟初始化。
// 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; }
}
}
回答by blowdart
public sealed class Singleton
{
private static readonly Singleton instance = new Singleton();
private Singleton(){}
public static Singleton Instance
{
get
{
return instance;
}
}
}
There's no ambiguity in .NET around initialization order; but this raises threading issues.
有在.NET中没有歧义各地初始化顺序; 但这会引发线程问题。
回答by Jon Limjap
According to Jon Skeet in Implementing the Singleton Pattern in C#the code you posted is actually considered as bad code, because it appears broken when checked against the ECMA CLI standard.
根据 Jon Skeet 在用 C# 实现单例模式中的说法,您发布的代码实际上被认为是坏代码,因为在根据 ECMA CLI 标准进行检查时,它似乎已损坏。
Also watch out: everytime you instantiate your object with a new type of T, it becomes another instance; it doesn't get reflected in your original singleton.
还要注意:每次使用新类型的 T 实例化对象时,它都会成为另一个实例;它不会反映在您原来的单身人士中。
回答by Wyzfen
I quite liked your original answer - the only thing missing (according to the link posted by blowdart) is to make the _instance variable volatile, to make sure it has actually been set in the lock. I actually use blowdarts solution when I have to use a singleton, but I dont have any need to late-instantiate etc.
我非常喜欢您的原始答案 - 唯一缺少的东西(根据 blowdart 发布的链接)是使 _instance 变量可变,以确保它实际上已设置在锁中。当我必须使用单例时,我实际上使用了吹镖解决方案,但我不需要后期实例化等。
回答by Jonathan Allen
You don't need all that, C# already has a good singleton pattern built-in.
您不需要所有这些,C# 已经内置了一个很好的单例模式。
static class Foo
If you need anything more interesting than that, chances are your new singleton is going to be just different enough that your generic pattern is going to be useless.
如果您需要比这更有趣的东西,那么您的新单例很可能会完全不同,以至于您的通用模式将毫无用处。
EDIT: By "anything more interesting" I'm including inheritance. If you can inherit from a singleton, it isn't a singleton any more.
编辑:通过“任何更有趣的东西”,我包括继承。如果您可以从单例继承,那么它就不再是单例了。
回答by Ilya Ryzhenkov
This code won't compile, you need "class" constraint on T.
此代码无法编译,您需要对 T 进行“类”约束。
Also, this code requires public constructor on target class, which is not good for singleton, because you can't control at compile time that you obtain (single) instance only via Instance property (or field). If you don't have any other static members except Instance, you are ok to go with just this:
此外,此代码需要目标类上的公共构造函数,这对单例不利,因为您无法在编译时控制仅通过 Instance 属性(或字段)获取(单个)实例。如果您没有除 Instance 之外的任何其他静态成员,则可以仅使用以下方法:
class Foo
{
public static readonly Instance = new Foo();
private Foo() {}
static Foo() {}
}
It is thread safe (guaranteed by CLR) and lazy (instance is created with first access to type). For more discussion about BeforeFieldInit and why we need static constructor here, see https://csharpindepth.com/articles/BeforeFieldInit.
它是线程安全的(由 CLR 保证)和惰性的(实例是在第一次访问类型时创建的)。有关 BeforeFieldInit 的更多讨论以及为什么我们需要静态构造函数,请参阅https://csharpindepth.com/articles/BeforeFieldInit。
If you want to have other public static members on type, but create object only on access to Instance, you may create nested type, like in https://csharpindepth.com/articles/Singleton
如果您想在类型上拥有其他公共静态成员,但仅在访问实例时创建对象,您可以创建嵌套类型,如https://csharpindepth.com/articles/Singleton
回答by Wayne Bloss
I don't think that you really want to "burn your base class" so that you can save 2 lines of code. You don't really need a base class to implement singleton.
我不认为你真的想“烧掉你的基类”,这样你就可以节省 2 行代码。你真的不需要基类来实现单例。
Whenever you need a singleton, just do this:
每当您需要单例时,只需执行以下操作:
class MyConcreteClass
{
#region Singleton Implementation
public static readonly Instance = new MyConcreteClass();
private MyConcreteClass(){}
#endregion
/// ...
}
回答by Binoj Antony
More details on this answer on a different thread : How to implement a singleton in C#?
有关不同线程上此答案的更多详细信息:如何在 C# 中实现单例?
However the thread doesn't use generic.
但是该线程不使用generic。
回答by dr. evil
I was looking for a better Singleton pattern and liked this one. So ported it to VB.NET, can be useful for others:
我一直在寻找更好的单例模式并喜欢这个模式。所以将它移植到 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
回答by dr. evil
My contribution for ensuring on demand creation of instance data:
我对确保按需创建实例数据的贡献:
/// <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;
}
}
}