实现单例模式C#版本
2015-08-21 16:25
246 查看
对于单例模式先来一个C#版本的初级不能用的版本:
版本一不可行方法:
之所以说这是一个不能用的初级版本,因为它仅仅能用在单线程的情况下。在多线程并发的情况下是不能保持单例的。
这里的不安全的地方是,多个线程同时对instance判断都为null,然后都new一个实例,所以要在判instance为null的那段代码加互斥锁。
版本二可行低效方法:
但是这种互斥锁是很消耗操作的,在没有必要的时候,尽量少做互斥锁。
所以做一个轻微的调整:
忽然发现这同样是不能多线程的,所以要在加一层对instance的判断null。
版本三可行方法:
这样就能够支持多线程了,是一种可行的方法。
版本四推荐的版本:
下面对静态构造函数做一个科普:
静态构造函数用来初始化静态变量,这个构造函数是属于类的,而不是属于哪个实例的。
就是说这个构造函数只会被执行一次。也就是在创建第一个实例或引用任何静态成员之前,由.NET自动调用。
静态构造函数的特点:
1.静态构造函数既没有访问修饰符,也没有参数。
2.在创建第一个实例或引用任何静态成员之前,将自动调用静态构造函数来初始化类,也就是无法直接调用静态构造函数,也无法控制什么时候执行静态构造函数。
3.一个类只能有一个静态构造函数,最多只能运行一次。
4.静态构造函数不可以被继承。
5.如果没有静态构造函数,而类中的静态成员有初始值,那么编译器会自动生成默认的静态构造函数。
从这里可以看出静态构造函数的调用时机不是由程序员掌控的,而是当.NET运行时发现第一次使用一个类型的时候自动调用该类型的静态构造函数。
但是这种方法会过早的穿件实例,从而降低了内存的使用效率。
版本五更高级的版本:
现在想做的就是不要一碰到Singleton就申请一个静态实例,要等到我调用getInstance的时候才申请实例空间。所以做一个内部类
版本一不可行方法:
public class Singleton { private Singleton() {} private static Singleton instance = null; public static Singleton getInstance() { if(instance == null) instance = new Singleton(); return instance; } }
之所以说这是一个不能用的初级版本,因为它仅仅能用在单线程的情况下。在多线程并发的情况下是不能保持单例的。
这里的不安全的地方是,多个线程同时对instance判断都为null,然后都new一个实例,所以要在判instance为null的那段代码加互斥锁。
版本二可行低效方法:
public class Singleton { private Singleton() {} private static Singleton instance = null; private static readonly object syncobj = new object(); public static Singleton getInstance() { lock(syncobj) { if(instance == null) instance = new Singleton(); } return instance; } }
但是这种互斥锁是很消耗操作的,在没有必要的时候,尽量少做互斥锁。
所以做一个轻微的调整:
public class Singleton { private Singleton() {} private static Singleton instance = null; private static readonly object syncobj = new object(); public static Singleton getInstance() { if(instance == null) { lock(syncobj) { instance = new Singleton(); } } return instance; } }
忽然发现这同样是不能多线程的,所以要在加一层对instance的判断null。
版本三可行方法:
public class Singleton { private Singleton() {} private static Singleton instance = null; private static readonly object syncobj = new object(); public static Singleton getInstance() { if(instance == null) { lock(syncobj) { if(instace == null) { instance = new Singleton(); } } } return instance; } }
这样就能够支持多线程了,是一种可行的方法。
版本四推荐的版本:
public class Singleton { private Singleton() {} private static Singleton instance = null; //静态构造函数,对静态成员变量初始化 static Singleton() { instance = new Singleton(); } public static Singleton getInstance() { return instance; } }
下面对静态构造函数做一个科普:
静态构造函数用来初始化静态变量,这个构造函数是属于类的,而不是属于哪个实例的。
就是说这个构造函数只会被执行一次。也就是在创建第一个实例或引用任何静态成员之前,由.NET自动调用。
静态构造函数的特点:
1.静态构造函数既没有访问修饰符,也没有参数。
2.在创建第一个实例或引用任何静态成员之前,将自动调用静态构造函数来初始化类,也就是无法直接调用静态构造函数,也无法控制什么时候执行静态构造函数。
3.一个类只能有一个静态构造函数,最多只能运行一次。
4.静态构造函数不可以被继承。
5.如果没有静态构造函数,而类中的静态成员有初始值,那么编译器会自动生成默认的静态构造函数。
从这里可以看出静态构造函数的调用时机不是由程序员掌控的,而是当.NET运行时发现第一次使用一个类型的时候自动调用该类型的静态构造函数。
但是这种方法会过早的穿件实例,从而降低了内存的使用效率。
版本五更高级的版本:
现在想做的就是不要一碰到Singleton就申请一个静态实例,要等到我调用getInstance的时候才申请实例空间。所以做一个内部类
public class Singleton { private Singleton(){} public static Singleton getInstance() { return Nested.instance; } //外部类只可以访问内部类的public和interal权限的字段、方法、属性 //嵌套类可以访问外部类的方法、属性、字段而不受访问修饰符的限制 class Nested { static Nested() { instance = new Singleton(); } internal static Singleton instance = null; } }
相关文章推荐
- 编写高质量代码改善C#程序的157个建议——建议106:为静态类添加静态构造函数
- c#用户控件的生命周期
- c#方法重载,可选参数,命名参数。
- c#方法重载,可选参数,命名参数。
- 记一次C#的web模拟登录抓取
- C#如何获取服务器时间
- 在C#中调用格式工厂进行任意视频格式到FLV的转换
- c#**************
- C#通过重写Panel改变边框颜色与宽度的方法
- C#获取“所有用户”的路径, 我的桌面,我的文档,我的音乐,我的图片等等目录
- 【完全开源】百度地图Web service API C#.NET版,带地图显示控件、导航控件、POI查找控件
- 编写高质量代码改善C#程序的157个建议——建议105:使用私有构造函数强化单例
- C#发起一个请求
- 退出(C# Winform)
- C#多线程编程实例 螺纹与窗口交互
- C# 百度百科查找信息
- C#实现读取注册表监控当前操作系统已安装软件变化的方法
- C#实现txt定位指定行完整实例
- 编写高质量代码改善C#程序的157个建议——建议104:用多态代替条件语句
- C# 转码