C# 创建单例的多种方式
作者:realyrare 时间:2023-03-17 05:23:48
关于为什么需要创建单例?这里不过多介绍,具体百度知。
关于C# 创建单例步骤或条件吧
1、声明静态变量;
2、私有构造函数(无法实例化)
3、静态创建实例的方法;至于我这里的Singleton是sealed ,只是为了防止被继承,其实有私有构造函数足够了,这里只是为了代码可读性。
第一种常见的方式创建单例:
/// <summary>
/// 不安全的单例
/// </summary>
public sealed class Singleton
{
private static Singleton _Singleton;
private Singleton() { }
public static Singleton GetSingleton()
{
if (_Singleton == null)
{
_Singleton = new Singleton();
}
return _Singleton;
}
}
注:为什么说是不安全的单例,多线程访问时可能会new多个对象...
第二种方式创建单例:
/// <summary>
/// (多线程)安全单例
/// </summary>
public sealed class Singleton
{
private static Singleton _Singleton;
private static readonly object obj = new object();
private Singleton() { }
public static Singleton GetSingleton()
{
if (_Singleton == null)
{
//加锁保护,在多线程下可以确保实例值被创建一次。缺点是每 次获取单例,都要进行判断,涉及到的锁和解锁比较耗资源。
lock (obj)
{
if (_Singleton == null)
{
_Singleton = new Singleton();
}
}
}
return _Singleton;
}
}
注:为了解决上面第一种方式创建的不安全实例问题应用而生。
第三种方式创建单例:
/// <summary>
/// 只读单例
/// </summary>
public sealed class Singleton
{
private static readonly Singleton instance = new Singleton();
private Singleton() { }
public static Singleton Instance
{
get
{
return instance;
}
}
}
/// <summary>
/// 基于上面的只读单例=自动属性只读单例(语法糖)
/// </summary>
public sealed class Singleton
{
private Singleton() { }
public static Singleton Instance { get; } = new Singleton();
}
注:只读属性式=>借助readonly属性,instance只被初始化一次,同样达到了单例的效果。在引用函数执行第一句话之前,instance其实已经被赋值了,并不是预期的 只有到访问Instance变量时才创建对象。
第四种方式创建单例:
/// <summary>
/// Singleton中加上静态构造函数。
/// </summary>
public sealed class Singleton
{
public static readonly Singleton instance = new Singleton();
private Singleton()
{
Console.WriteLine("初始化1!");
}
static Singleton()
{
}
public static Singleton Instance
{
get { return instance; }
}
}
注:为了解决(第三种只读属性实例)在执行第一句代码之前,实例已经被初始化问题。
第五种方式创建单例:
/// <summary>
/// 使用Lazy创建单例,默认是线程安全的
/// </summary>
public sealed class Singleton
{
private static readonly Lazy<Singleton> instance = new Lazy<Singleton>(() => new Singleton());//
private Singleton() { }
public static Singleton Instance
{
get
{
return instance.Value;
}
}
}
// 贴一下关于上面Lazy<T> s=new Lazy<T>()参数的定义;
// 摘要:
// 初始化System.Lazy`1类的新实例。 懒惰初始化时
// 发生时,使用指定的初始化函数和初始化模式。
// 参数:
// valueFactory:
// 被调用以生成延迟初始化值的委托是必需的参数
//
// isThreadSafe:
// 如果要使此实例可由多个线程同时使用,则为true; false
//使此实例一次只能由一个线程使用。
public Lazy(Func<T> valueFactory, bool isThreadSafe);
来源:https://www.cnblogs.com/mhg215/p/9795478.html
标签:c#,单例
![](/images/zang.png)
![](/images/jiucuo.png)
猜你喜欢
Java判断变量是否为空问题的方法总结
2023-02-03 12:23:09
mybatis多表查询的实现(xml方式)
2021-07-11 01:21:38
![](https://img.aspxhome.com/file/2023/5/79235_0s.png)
SpringCloud迈向云原生的步骤
2023-08-21 22:59:46
![](https://img.aspxhome.com/file/2023/2/95032_0s.png)
HashMap红黑树入门(实现一个简单的红黑树)
2022-10-18 13:52:35
![](https://img.aspxhome.com/file/2023/2/79292_0s.png)
Android仿知乎客户端关注和取消关注的按钮点击特效实现思路详解
2022-08-05 19:49:02
![](https://img.aspxhome.com/file/2023/5/94975_0s.png)
使用Spring Boot进行单元测试详情
2023-11-10 08:01:53
android ItemTouchHelper实现可拖拽和侧滑的列表的示例代码
2023-08-14 14:51:51
![](https://img.aspxhome.com/file/2023/8/100588_0s.gif)
Java实现的RSA加密解密算法示例
2022-05-03 09:20:38
关于MyBatis中SqlSessionFactory和SqlSession简解
2022-02-18 13:57:37
Java多线程状态及方法实例解析
2021-09-10 22:49:53
![](https://img.aspxhome.com/file/2023/7/74777_0s.png)
Java超详细讲解排序二叉树
2022-12-22 22:55:17
浅析C# 9.0 新特性之 Lambda 弃元参数
2022-05-08 16:28:22
![](https://img.aspxhome.com/file/2023/9/119569_0s.png)
IDEA使用SequenceDiagram插件绘制时序图的方法
2023-07-03 11:20:07
![](https://img.aspxhome.com/file/2023/4/86034_0s.png)
Unity3D 单例模式和静态类的使用详解
2022-09-22 08:16:19
C++ 中二分查找递归非递归实现并分析
2023-06-19 06:51:31
![](https://img.aspxhome.com/file/2023/9/128169_0s.png)
C#多线程中的异常处理操作示例
2023-07-16 06:10:10
![](https://img.aspxhome.com/file/2023/4/113824_0s.png)
macOS下Spring Boot开发环境搭建教程
2023-11-05 15:50:59
![](https://img.aspxhome.com/file/2023/1/85541_0s.jpg)
Android 仿硅谷新闻下拉刷新/上拉加载更多
2023-03-25 14:19:11
Java设计模式之工厂模式案例详解
2023-11-27 20:08:03
![](https://img.aspxhome.com/file/2023/2/60342_0s.png)
JavaWeb实现学生信息管理系统(2)
2022-03-04 02:31:12
![](https://img.aspxhome.com/file/2023/3/116833_0s.jpg)