泛型简单的来说就是用一个东西来满足多种不同类型的需求
历史:
最开始使用object来做万能类型,能使用object的原因是:
1.任何父类出现的地方,都可以用子类来代替
2.object是一切类型的父类
用object的问题:
1、装箱和拆箱问题
传入一个int值(栈)
object又在堆里面,如果把int传递进来,就会把值从栈里面copy到堆里
2、类型安全问题,可能会有,因为传递的对象是没有限制的
思考:为什么泛型方法支持不同类型的参数?
1.泛型声明方法时,没有写死类型,T是什么,不知道
2.T要等着调用的的时候才指定
设计思想:延迟声明:推迟一切可以推迟的,一切能晚点做的的事,就晚点做
泛型原理:
C#编译过程:
编译的时候确实不知道T是什么
机器码时候,必须类型是确认的
泛型是.net framework2.0出来的
包含以下升级才能支持
1.编译器能支持类型参数,用占位符表达
`1 `2表示有几个类型参数
2. CLR升级才能支持占位符,运行时,类型是确定了的,那就可以吧占位符再替换掉
泛型不是一个简单的语法糖,是框架升级支持的
泛型方法的性能跟普通方法是一致的,是最好的。
而且还能一个方法
一般我们把编辑器提供的便捷功能,称之为语法糖
泛型缓存(选修)
字典缓存:静态属性常住内存
private state Dictionary<Type, string>
WebService WCF都不能使用泛型,为什么?
跨语言,别的语言是否能用,是否支持泛型
服务在发布的时候是必须确定的,泛型在编译时确定不了
哪里用泛型? 泛型到底是干嘛的?
泛型方法:为了一个方法满足不同的类型的需求
泛型类:一个类,满足不同类型的需求 List Dictionary
泛型接口:一个接口,满足不同类型的需求
泛型委托:一个委托,满足不同类型的需求
泛型约束
没有约束,也导致什么类型都可能传入进来,有可能不安全
where T:BaseModel
基类约束:
1 可以把T当成基类---权利
2 T 必须是 BaseModel或者其子类
为什么要约束,因为有约束才有权利
自由主义的鼻祖洛克先生说过,有了法律,才有自由
where T:ISports
接口约束
where T: class
引用类型约束
where T:struct
值类型约束
where T:new()
无参数构造函数约束
20181212Advanced12Course2Reflection期开头
泛型的协变和逆变
父类:Bird
子类:Sparrow
List<Bird> birdList2 = new List<Sparrow>();//这个是错误的。不成立,语法不通过,原因是List<Bird>是一个类--List<Sparrow>也是一个类,没有父子关系
所以有了协变和逆变
协变:就是让右边可以用子类,让泛型用起来更方便
out修饰,协变后,T只能作为返回值,不能当参数
使用 public interface IEnumerable<out T> : IEnumerable来实现上面的集合
IEnumerable<Bird> birdList1 = new List<Bird>();
IEnumerable<Bird> birdList2 = new List<Sparrow>();//左父类,右子类。
逆变:就是让右边可以用父类,让泛型用起来更方便
in修饰,逆变后,T只能作为当参数 不能做返回值,
自定义接口: public interface ICustomerListIn<in T>
{
//T Get();//不能做返回值
void Show(T t);
}
ICustomerListIn<Sparrow> customerList2 = new CustomerListIn<Sparrow>();
ICustomerListIn<Sparrow> customerList1 = new CustomerListIn<Bird>();//左子类,右父类