如何在C#中实现单例?

时间:2008-10-29 13:04:39

标签: c# .net singleton

如何在C#中实现单例模式?我想把我的常量和一些基本功能放在其中,因为我在我的项目中使用它们。我想让它们'全局',而不需要手动绑定它们我创建的每个对象。

17 个答案:

答案 0 :(得分:28)

如果您只是存储一些全局值并且有一些不需要状态的方法,则不需要单例。只需使类及其属性/方法成为静态。

public static class GlobalSomething
{
   public static int NumberOfSomething { get; set; }

   public static string MangleString( string someValue )
   {
   }
}

当你有一个普通的有状态的类时,单例是最有用的,但你只需要其中一个。其他人提供的链接应该有助于探索Singleton模式。

答案 1 :(得分:7)

Singleton != Global。您似乎在寻找关键字static

答案 2 :(得分:4)

单身者只有在这两个条件成立时才有意义:

  1. 对象必须全局
  2. 只能存在对象的单个实例
  3. 请注意,#2并不意味着你喜欢对象只有一个实例 - 如果是这样的话,只需要实例化一次 - 这意味着必须(因为,这不是真的危险)只是一个单一的实例。

    如果你想要全局,只需创建一些(非符号)对象的全局实例(或使其成为静态或其他)。 如果你只想要一个实例,那么static就是你的朋友。此外,只需实例化一个对象。

    无论如何,这都是我的意见。

答案 3 :(得分:4)

你可以真正简化单例实现,这就是我使用的:

    internal FooService() { }        
    static FooService() { }

    private static readonly FooService _instance = new FooService();

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

答案 4 :(得分:4)

嗯,这一切看起来有点复杂。

为什么需要依赖注入框架才能获得单例?对于某些企业应用来说,使用IOC容器是好的(只要它当然没有过度使用),但是,啊,这个家伙只是想知道实现这种模式。

为什么不总是急切地实例化,然后提供一个返回静态的方法,然后上面写的大部分代码就消失了。按照旧的C2格言 - DoTheSimplestThingThatCouldPossiblyWork ...

答案 5 :(得分:3)

忽略你是否应该使用Singleton模式的问题,我已经在其他地方讨论过了,我会实现这样的单例:

/// <summary>
/// Thread-safe singleton implementation
/// </summary>
public sealed class MySingleton {

    private static volatile MySingleton instance = null;
    private static object syncRoot = new object();

    /// <summary>
    /// The instance of the singleton
    /// safe for multithreading
    /// </summary>
    public static MySingleton Instance {
        get {
            // only create a new instance if one doesn't already exist.
            if (instance == null) {
                // use this lock to ensure that only one thread can access
                // this block of code at once.
                lock (syncRoot) {
                    if (instance == null) {
                        instance = new MySingleton();
                    }
                }
            }
            // return instance where it was just created or already existed.
            return instance;
        }
    }


    /// <summary>
    /// This constructor must be kept private
    /// only access the singleton through the static Instance property
    /// </summary>
    private MySingleton() {

    }

}

答案 6 :(得分:3)

如果你想要一个松散耦合的设计,静态单例几乎是一种反模式。尽可能避免,除非这是一个非常简单的系统,否则我建议您查看可用的许多依赖注入框架之一,例如http://ninject.org/http://code.google.com/p/autofac/

要在autofac中注册/使用配置为单身的类型,您可以执行以下操作:

var builder = new ContainerBuilder()
builder.Register(typeof(Dependency)).SingletonScoped()
builder.Register(c => new RequiresDependency(c.Resolve<Dependency>()))

var container = builder.Build();

var configured = container.Resolve<RequiresDependency>();

顺便说一句,接受的答案是一个可怕的解决方案,至少检查实际实施该模式的人。

答案 7 :(得分:3)

我建议您阅读MSDN上提供的文章Exploring the Singleton Design Pattern。它详细介绍了框架的功能,使模式易于实现。

顺便说一句,我会查看related reading on SO regarding Singletons

答案 8 :(得分:2)

我喜欢这种模式,虽然它不会阻止某人创建非单例实例。有时可以更好地教育团队中的开发人员使用正确的方法而不是英雄的长度,以防止某些傻瓜以错误的方式使用您的代码......

    public class GenericSingleton<T> where T : new()
    {
        private static T ms_StaticInstance = new T();

        public T Build()
        {
            return ms_StaticInstance;
        }
    }

...
    GenericSingleton<SimpleType> builder1 = new GenericSingleton<SimpleType>();
    SimpleType simple = builder1.Build();

这将为您提供单个实例(以正确方式实例化)并且实际上将是惰性的,因为在调用Build()之前不会调用静态构造函数。

答案 9 :(得分:2)

public class Globals
{
    private string setting1;
    private string setting2;

    #region Singleton Pattern Implementation

    private class SingletonCreator
    {
        internal static readonly Globals uniqueInstance = new Globals();

        static SingletonCreator()
        {
        }
    }

    /// <summary>Private Constructor for Singleton Pattern Implementaion</summary>
    /// <remarks>can be used for initializing member variables</remarks>
    private Globals()
    {

    }

    /// <summary>Returns a reference to the unique instance of Globals class</summary>
    /// <remarks>used for getting a reference of Globals class</remarks>
    public static Globals GetInstance
    {
        get { return SingletonCreator.uniqueInstance; }
    }

    #endregion

    public string Setting1
    {
        get { return this.setting1; }
        set { this.setting1 = value; }
    }

    public string Setting2
    {
        get { return this.setting2; }
        set { this.setting2 = value; }
    }

    public static int Constant1 
    {
        get { reutrn 100; }
    }

    public static int Constat2
    {
        get { return 200; }
    }

    public static DateTime SqlMinDate
    {
        get { return new DateTime(1900, 1, 1, 0, 0, 0); }
    }

}

答案 10 :(得分:1)

嗯...很少有相关功能的常量...通过枚举最好不会实现吗?我知道你可以使用方法和所有方法在Java中创建自定义枚举,在C#中也应该可以实现,如果不是直接支持,那么可以使用私有构造函数的简单类单例来完成。

如果你的常量在语义上是相关的,你应该考虑枚举(或等效的概念),你将获得const静态变量的所有优点+你将能够利用编译器的类型检查。

我的2美分

答案 11 :(得分:1)

就个人而言,我会选择像Unity一样的依赖注入框架,它们都能够在容器中配置单例项,并通过从类依赖转移到接口依赖来改善耦合。

答案 12 :(得分:1)

您所描述的仅仅是静态函数和常量,不是单例。单例设计模式(很少需要)描述了一个 实例化的类,但只在第一次使用时自动执行一次。

它结合了延迟初始化和检查以防止多次实例化。它只对包含一些物理上奇异的概念的类非常有用,例如硬件设备的包装。

静态常量和函数就是:完全不需要实例的代码。

问问自己:“如果有多个实例,这个类会破坏吗?”如果答案是否定的,则不需要单身人士。

答案 13 :(得分:0)

隐藏公共构造函数,添加私有静态字段以保存此唯一实例,并添加静态工厂方法(使用延迟初始化程序)以返回该单个实例

public class MySingleton   
{  
    private static MySingleton sngltn; 
    private static object locker;  
    private MySingleton() {}   // Hides parameterless ctor, inhibits use of new()   
    public static MySingleton GetMySingleton()       
    {     
        lock(locker)
            return sngltn?? new MySingleton();
    }   
}

答案 14 :(得分:0)

我使用Singleton模式为我的项目编写了一个类。这是非常容易使用。希望它能为你效劳。请找到以下代码。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace TEClaim.Models
{
public class LogedinUserDetails
{
    public string UserID { get; set; }
    public string UserRole { get; set; }
    public string UserSupervisor { get; set; }
    public LogedinUserDetails()
    {

    }

    public static LogedinUserDetails Singleton()
    {
        LogedinUserDetails oSingleton;

        if (null == System.Web.HttpContext.Current.Session["LogedinUserDetails"])
        {               
            oSingleton = new LogedinUserDetails();
            System.Web.HttpContext.Current.Session["LogedinUserDetails"] = oSingleton;
        }
        else
        {              
            oSingleton = (LogedinUserDetails)System.Web.HttpContext.Current.Session["LogedinUserDetails"];
        }

        //Return the single instance of this class that was stored in the session
        return oSingleton;
    }
}
}

现在您可以像这样设置应用程序中上述代码的变量值。

[HttpPost]
public ActionResult Login(FormCollection collection)
{
  LogedinUserDetails User_Details = LogedinUserDetails.Singleton();
  User_Details.UserID = "12";
  User_Details.UserRole = "SuperAdmin";
  User_Details.UserSupervisor = "815978";
  return RedirectToAction("Dashboard", "Home");
}

你可以像这样检索那些值..

public ActionResult Dashboard()
    {
        LogedinUserDetails User_Details = LogedinUserDetails.Singleton();
        ViewData["UserID"] = User_Details.UserID;
        ViewData["UserRole"] = User_Details.UserRole;
        ViewData["UserSupervisor"] = User_Details.UserSupervisor;

        return View();
    }

答案 15 :(得分:0)

在c#中它可能是(线程安全以及延迟初始化):

public sealed class MySingleton
{
    static volatile Lazy<MySingleton> _instance = new Lazy<MySingleton>(() => new MySingleton(), true);
    public static MySingleton Instance => _instance.Value;
    private MySingleton() { }
}

答案 16 :(得分:0)

public class Singleton
{
   private static Singleton _instance;
   public static Singleton Instance => _instance ?? (_instance = new Singleton());
}