c#泛型与单例
你好! 这是 泛型与单例 所展示的欢迎页。
单例类
普通单例类:
/// <summary>
/// 单例模式的实现
/// </summary>
public class Singleton
{
// 定义一个静态变量来保存类的实例
private static Singleton uniqueInstance;
// 定义一个标识确保线程同步
private static readonly object locker = new object();
// 定义私有构造函数,使外界不能创建该类实例
private Singleton()
{
}
/// <summary>
/// 定义公有方法提供一个全局访问点,
/// 同时你也可以定义公有属性来提供全局访问点
/// </summary>
/// <returns></returns>
public static Singleton GetInstance()
{
// 当第一个线程运行到这里时,此时会对locker对象 "加锁",
// 当第二个线程运行该方法时,
/// 首先检测到locker对象为"加锁"状态,
/// 该线程就会挂起等待第一个线程解锁
/// lock语句运行完之后(即线程运行完之后)
/// 会对该对象"解锁"
// 双重锁定只需要一句判断就可以了
if (uniqueInstance == null)
{
lock (locker)
{
// 如果类的实例不存在则创建,否则直接返回
if (uniqueInstance == null)
{
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
}
单例泛型类-作为基类
特点1:where 约束:引用类型/值类型
where T:class 是 引用类型约束,使用class关键字
引用类型约束将一个类型形参限定为引用类型。
引用类型一般是用户定义的类型,包含类/接口/委托/字符串和数组类型。
在这个where子句中,class关键字是指定T必须是引用类型。因此,尝试对T使用值类型,将会导致编译错误。
where T:struct 是 值类型约束,使用struct关键字
值类型约束将一个类型形参限定为值类型。
值类型派生于System.ValueType类型。基元和结构都是值类型。
在该形式中,struct关键字指定T必须是值类型。因此,尝试对T使用引用类型,将导致编译错误。
特点2:where 约束:new()【new不支持私有的无参构造函数】
使用new()约束时应当注意:
1.new()约束可以与其他约束一起使用,但必须位于约束列表的末端
2.new()约束仅允许开发人员使用无参数的构造函数构造一个对象,
即使同时存在其他的构造函数也是如此。即不允许给类型形参的构造
函数传递实参。
3.不可以同时使用new()约束和值类型约束。因为值类型都隐式的提
供了一个无参公共构造函数。
就如同定义接口时指定访问类型为public一样,编译器会报错,因为接口一定是public的。
特点3:双重线程锁,更加安全
class Singleton<T> where T: class,new()
{
private static T _instance;
private static readonly object syslock=new object();
public static T getInstance()
{
if (_instance == null)
{
lock (syslock) {
if (_instance == null)
{
//T如果没有约束new() 这里是不允许new的
_instance = new T();
}
}
}
return _instance;
}
}
以下代码是 不支持私有的无参构造函数的单例泛型
public abstract class BaseInstance<T> where T : class,new()
{
private readonly static object lockObj = new object();
private static T instance = null;
public static T Instance
{
get
{
if (instance == null)
{
lock (lockObj)
{
if (instance == null)
{
instance = new T();
}
}
}
return instance;
}
}
}
以下代码是 支持私有的无参构造函数的单例泛型
public class BaseInstance<T> where T : class//new(),new不支持非公共的无参构造函数
{
/*
* 单线程测试通过!
* 多线程测试通过!
* 根据需要在调用的时候才实例化单例类!
*/
private static T _instance;
private static readonly object SyncObject = new object();
public static T Instance
{
get
{
if (_instance == null)//没有第一重 singleton == null 的话,每一次有线程进入 GetInstance()时,均会执行锁定操作来实现线程同步,
//非常耗费性能 增加第一重singleton ==null 成立时的情况下执行一次锁定以实现线程同步
{
lock (SyncObject)
{
if (_instance == null)//Double-Check Locking 双重检查锁定
{
//_instance = new T();
//需要非公共的无参构造函数,
//不能使用new T() ,new不支持非公共的无参构造函数
_instance = (T)Activator.CreateInstance(typeof(T), true);
//第二个参数防止异常:“没有为该对象定义无参数的构造函数。”
}
}
}
return _instance;
}
}
public static void SetInstance(T value)
{
_instance = value;
}
}
单例泛型的使用-继承
作为面向对象的三大特性:封装、继承、多态 (抽象,严格来说不算)。
继承之后,可以调用父类的方法【GetInstance()】,获取到本类(子类)的实例【new()之后的对象】,全局单独存在,独一无二。
这个实例可以调用本类的所有方法和属性进行操作。
class myclass : Singleton<myclass> {
public void ss() {
Console.WriteLine("111");
}
}
///在main或者指定函数调用如下:
myclass.getInstance().ss();
泛型单例使用方法2-封装
调用类的静态方法 ,直接返回该类型的实例:
public class NetIO
{
public static NetIO GetInstance()
{
return SingletonProvider<NetIO>.Instance;
}
public NetIO()
{
this.NetIoCreateTime = DateTime.Now;
}
public DateTime NetIoCreateTime
{
get {
return _ct; }
set {
_ct = value; }
}
private DateTime _ct;
}
C#在Unity中的单例
using System;
using UnityEngine;
public class SingletonProvider<T> where T : class ,new()
{
private SingletonProvider()
{
}
private static T _instance;
// 用于lock块的对象
private static readonly object _synclock = new object();
public static T Instance
{
get
{
if (_instance == null)
{
lock (_synclock)
{
if (_instance == null)
{
// 若T class具有私有构造函数,那么则无法使用SingletonProvider<T>来实例化new T();
_instance = new T();
//测试用,如果T类型创建了实例,则输出它的类型名称
Debug.Log("{0}:创建了单例对象" + typeof(T).Name);
}
}
}
return _instance;
}
set {
_instance = value; }
}
}