什么是C#中的单例?

什么是单例,什么时候应该使用它?

192485 次浏览

它是什么:在应用程序的生命周期中只有一个持久实例的类。请参阅单例模式

何时应该使用它:尽可能少。只有当您绝对肯定时,您才需要它。我不愿意说“永远不会”,但通常有更好的选择,比如依赖注入或简单的静态类。

单例是一个类,它只允许创建自身的一个实例,并提供对所述实例的简单、轻松的访问。单例前提是软件开发中的一种模式。

有一个C#实现“在C#中实现单例模式”,它涵盖了您需要了解的大部分内容-包括一些关于螺纹安全的好建议。

老实说,你很少需要实现一个单例——在我看来,它应该是你应该注意的事情之一,即使它不经常使用。

单例是这样的:http://en.wikipedia.org/wiki/Singleton_pattern

我不知道C#,但它实际上在所有语言中都是一样的,只是实现不同。

在可能的情况下,您通常应该避免单例,但在某些情况下,它非常方便。

对不起我的英语;)

这是一种设计模式,并不是C#特有的。在互联网上有更多关于它的信息,比如在这个维基百科文章上。

软件工程中,单例 模式是一种设计模式 用于限制 类转换为一个对象。这很有用 当恰好需要一个对象来 协调整个系统的行动。 这个概念有时是泛化的。 到操作更多的系统 当只有一个对象时高效 存在,或限制 实例化到一定数量的 对象(例如,五个)。有些人认为 一个反模式,判断它是 过度使用,引入不必要的 在以下情况下的限制: 类的实例实际上不是 必需,并引入全局状态 到应用程序中.

如果你想要一个只能实例化一次的类,你应该使用它。

单例(这与C#无关,它是一种OO设计模式)是指您希望在整个应用程序中只允许创建一个类的实例。使用通常包括全球资源,尽管我会说从个人经验来看,它们往往是巨大痛苦的根源。

虽然单例只能有一个实例,但它与静态类不同。静态类只能包含静态方法,并且永远不能被实例化,而单例的实例可以以与任何其他对象相同的方式使用。

你要的是C#。小例子:


public class Singleton
{
private Singleton()
{
// Prevent outside instantiation
}


private static readonly Singleton _singleton = new Singleton();


public static Singleton GetSingleton()
{
return _singleton;
}
}

在C#中实现Singleton的另一种方法,我个人更喜欢这种方法,因为您可以将Singeton类的实例作为属性而不是方法来访问。

public class Singleton
{
private static Singleton instance;


private Singleton() { }


public static Singleton Instance
{
get
{
if (instance == null)
instance = new Singleton();
return instance;
}
}


//instance methods
}

但是,据我所知,这两种方式都被认为是“正确的”,所以这只是个人喜好。

using System;
using System.Collections.Generic;
class MainApp
{
static void Main()
{
LoadBalancer oldbalancer = null;
for (int i = 0; i < 15; i++)
{
LoadBalancer balancerNew = LoadBalancer.GetLoadBalancer();


if (oldbalancer == balancerNew && oldbalancer != null)
{
Console.WriteLine("{0} SameInstance {1}", oldbalancer.Server, balancerNew.Server);
}
oldbalancer = balancerNew;
}
Console.ReadKey();
}
}


class LoadBalancer
{
private static LoadBalancer _instance;
private List<string> _servers = new List<string>();
private Random _random = new Random();


private static object syncLock = new object();


private LoadBalancer()
{
_servers.Add("ServerI");
_servers.Add("ServerII");
_servers.Add("ServerIII");
_servers.Add("ServerIV");
_servers.Add("ServerV");
}


public static LoadBalancer GetLoadBalancer()
{
if (_instance == null)
{
lock (syncLock)
{
if (_instance == null)
{
_instance = new LoadBalancer();
}
}
}


return _instance;
}


public string Server
{
get
{
int r = _random.Next(_servers.Count);
return _servers[r].ToString();
}
}
}

我从DoFactory.com中获取代码,没有什么特别的,但我发现这比foo和bar的例子好得多。另外,Judith Bishop关于C#3.0设计模式的书中有关于Mac Dock中活动应用程序的示例。

如果你看一下代码,我们实际上是在为了循环上构建新对象,因此创建了新对象,但重用了实例,其结果是OldBalancer和NewBalancer具有相同的实例,这是怎么回事?这是由于在函数GetLoadBalancer()上使用的静态的关键字,尽管具有随机列表的不同服务器值,但在GetLoadBalancer()上的静态属于类型本身,而不是属于特定对象。

此外,这里还有双重检查锁定

if (_instance == null)
{
lock (syncLock)
{
if (_instance == null)

从MSDN开始

关键字LOCK确保一个线程不会在另一个线程处于临界区时进入代码的临界区。如果另一个线程试图输入锁定的代码,它将等待,阻塞,直到对象被释放。

所以每次互斥锁都会发出,即使它不需要,这是不必要的,所以我们有空检查。

希望它能帮助清理更多。

如果我的理解是错误的,请发表评论。

我用它来查找数据。从数据库加载一次。

public sealed class APILookup
{
private static readonly APILookup _instance = new APILookup();
private Dictionary<string, int> _lookup;


private APILookup()
{
try
{
_lookup = Utility.GetLookup();
}
catch { }
}


static APILookup()
{
}


public static APILookup Instance
{
get
{
return _instance;
}
}
public Dictionary<string, int> GetLookup()
{
return _lookup;
}


}

什么是单例:
它是一个类,只允许创建其自身的一个实例,并且通常提供对该实例的简单访问。

什么时候应该使用:
这要看情况。

注意:请不要在数据库连接上使用,要获得详细答案,请将@Chad Grant的答案提到

下面是Singleton的一个简单示例:

public sealed class Singleton
{
private static readonly Singleton instance = new Singleton();


// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static Singleton()
{
}


private Singleton()
{
}


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

您也可以使用Lazy<T>来创建Singleton

有关使用Lazy<T>的更详细示例,请参阅看这里

E.X您可以对需要注入的全局信息使用单例。

在我的例子中,我将记录的用户详细信息(用户名、权限等)保存在全局静态类中。当我尝试实现单元测试时,我无法将依赖项注入控制器类。因此,我将静态类更改为单例模式。

public class SysManager
{
private static readonly SysManager_instance = new SysManager();


static SysManager() {}


private SysManager(){}


public static SysManager Instance
{
get {return _instance;}
}
}

http://csharpindepth.com/articles/general/singleton.aspx#cctor.

我知道现在回答这个问题已经很晚了,但是使用auto-property,你可以做这样的事情:

public static Singleton Instance { get; } = new Singleton();

其中,Singleton是您的类,并且可以是VIA,在这种情况下,是只读属性Instance

线程安全单例,不使用锁,也没有惰性实例化。

此实现具有静态构造函数,因此它在每个应用程序域中只执行一次。

public sealed class Singleton
{


static Singleton(){}


private Singleton(){}


public static Singleton Instance { get; } = new Singleton();


}

在C#中实现单例模式的第四个版本

对于此实现(仅此一种),您可以采用的一种捷径是将实例设置为公共静态只读变量,并完全删除该属性。这使得基本框架代码非常小!

public sealed class Singleton
{
public static readonly Singleton Instance = new Singleton();


static Singleton()
{
}


private Singleton()
{
}
}