什么是C#中的单身人士?

时间:2010-01-28 15:38:00

标签: c# .net singleton

非常直截了当的问题。

什么是单身人士,何时应该使用它?

16 个答案:

答案 0 :(得分:128)

单例是一个只允许创建自己的一个实例的类 - 并且可以简单,轻松地访问所述实例。单例前提是跨软件开发的模式。

有一个C#实现"Implementing the Singleton Pattern in C#"涵盖了你需要知道的大部分内容 - 包括一些关于线程安全的好建议。

说实话,你需要实现一个单例是非常罕见的 - 在我看来,它应该是你应该注意的事情之一,即使它不经常使用。

答案 1 :(得分:48)

你问过C#。琐碎的例子:


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

    private static readonly Singleton _singleton = new Singleton();

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

答案 2 :(得分:39)

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

何时应该使用它尽可能少。只有当你完全确定时才需要它。我不愿意说“从不”,但通常有一个更好的选择,例如依赖注入或简单的静态类。

答案 3 :(得分:24)

在c#中实现单例的另一种方法,我个人更喜欢这种方式,因为你可以将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
    }

但是,据我所知,这两种方式都被认为是对的'所以它只是个人风格。

答案 4 :(得分:10)

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。

如果查看代码,我们实际上是在 for 循环上构建新对象,这样就可以创建新对象但重用实例,因为oldbalancer和newbalancer具有相同的实例,如何?由于 GetLoadBalancer()上使用了 static 关键字,尽管服务器值不同是随机列表,但 GetLoadBalancer()上的静态属于类型本身而不是特定对象。

此外还有double check locking

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

来自MSDN

  
    

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

  

所以每次都会发出互斥锁,即使它不需要也不需要,所以我们进行空检查。

希望它有助于清理更多。

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

答案 5 :(得分:6)

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

答案 6 :(得分:5)

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

答案 7 :(得分:2)

这是一种设计模式,并不是特定于c#。更多关于互联网和SO的内容,例如wikipedia article

  

在软件工程中,单身人士   模式是一种设计模式   用来限制a的实例化   类到一个对象。这很有用   什么时候只需要一个对象   协调整个系统的行动。   这个概念有时会被概括   到运行更多的系统   只有一个对象时有效   存在,或限制   实例化到一定数量的   对象(比如说五个)。有些人认为   反模式,判断它是   过度使用,引入不必要的   鞋底情况的局限性   实际上并不是一个类的实例   要求,并介绍全球状态   进入申请表。

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

答案 8 :(得分:2)

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

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;
        }

    }

答案 9 :(得分:2)

什么是单身人士:
它是一个只允许创建自己的一个实例的类,并且通常可以简单地访问该实例。

您应该何时使用:
这取决于具体情况。

注意:请不要在数据库连接上使用,请详细解答refer @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

See here了解使用Lazy<T>

的更详细示例

答案 10 :(得分:1)

以下是单身人士:http://en.wikipedia.org/wiki/Singleton_pattern

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

一般情况下,你应该尽可能避免使用单身人士,但在某些情况下,这是非常方便的。

对不起我的英文;)

答案 11 :(得分:1)

Singleton类用于为整个应用程序域创建单个实例。

public class Singleton
{
    private static Singleton singletonInstance = CreateSingleton();

    private Singleton()
    {
    }

    private static Singleton CreateSingleton()
    {
        if (singletonInstance == null)
        {
            singletonInstance = new Singleton();
        }

        return singletonInstance;
    }

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

this article it is described 中我们如何使用readonly变量创建线程安全的单例类及其在应用程序中的实际用途。

答案 12 :(得分:1)

不使用锁也没有延迟实例化的线程安全单例。

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

public sealed class Singleton
{

    static Singleton(){}

    private Singleton(){}

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

}

答案 13 :(得分:0)

E.X您可以将Singleton用于需要注入的全局信息。

就我而言,我将Logged用户的详细信息(用户名,权限等)保留在Global Static Class中。当我尝试实现单元测试时,我无法将依赖项注入Controller类。因此,我将我的静态类更改为单例模式。

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

答案 14 :(得分:0)

我知道回答这个问题已经很晚了,但是使用自动属性,您可以执行以下操作:

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

您在Singleton上课的地方并且可以通过,在这种情况下,它是只读属性Instance

答案 15 :(得分:0)

当我们需要确保仅创建特定类的一个实例,然后为整个应用程序提供对该实例的简单全局访问时,我们需要在C#中使用Singleton设计模式。

可以使用Singleton设计模式的实时方案: 服务代理:众所周知,调用服务API是应用程序中的一项广泛操作。花费大部分时间的过程是创建服务客户端以调用服务API。如果将服务代理创建为Singleton,则它将提高应用程序的性能。

外观:您也可以将数据库连接创建为Singleton,以提高应用程序的性能。

日志:在应用程序中,对文件执行I / O操作是一项昂贵的操作。如果您将Logger创建为Singleton,则它将提高I / O操作的性能。

数据共享:如果您有任何常量值或配置值,则可以将这些值保留在Singleton中,以便应用程序的其他组件可以读取它们。

缓存:众所周知,从数据库中获取数据是一个耗时的过程。在您的应用程序中,您可以将主服务器和配置缓存在内存中,这将避免DB调用。在这种情况下,可以使用Singleton类以有效的方式处理具有线程同步的缓存,从而大大提高应用程序的性能。

C#中单例设计模式的缺点 在C#中使用Singleton设计模式的缺点如下:

单元测试非常困难,因为它将全局状态引入到应用程序中。 它减少了程序内并行的可能性,因为要在多线程环境中访问单例实例,您需要使用锁定来序列化对象。

我从下面的文章中引用了这一点。

https://dotnettutorials.net/lesson/singleton-design-pattern/