1-泛型为什么存在,类型参数,默认值
2-泛型约束,子类,自引用,静态数据,转换
3-协变,逆变,不变
reuse两种形式
1.继承
2.泛型
<T>类型参数
var st=new Stack<int>()//特化
public T Pop();//不是泛型方法,只是泛型类型中的1个普通方法
运行时类型参数必须被特化
泛型的作用-避免类型膨胀和成员膨胀
用Object类型的缺点:使用时比较麻烦,需要强转/as
1.需要装箱
2.需要向下转换,这种转换在编译时无法进行检查-运行时错误
方法重载-函数名相同,参数列表不同,和返回值无关
方法逻辑相同时,用泛型替代
只有类型和方法可以引入类型参数<T>
其他的类型成员不可以声明类型参数,但是可以使用它们所在泛型类型的类型参数
类型-class,interface,delegate,struct可以引入类型参数
方法可以引入类型参数
属性不能引入,但是可以使用
泛型类型/泛型方法可以有多个类型参数
类型参数<T>命名可以有描述性
<TId>
<TKey>
<TValue>
泛型方法的名称可以被重载,只要参数列表不同
typeof操作符获取类型
Type t=typeof(xxx);
开放的泛型类型是和反射API一起使用的
default关键字获取默认值
引用类型-null
值类型-按位归0的值
泛型的约束:
T必须是某个父类的子类
T必须实现了某个接口
T必须是引用类型
T必须是值类型,不包括可空的值类型,比如int?
T必须有1个无参的构造器
U继承于T
T继承于SomeClass并且实现Interface1这个接口
U必须有1个无参的构造函数
泛型类型的约束不仅可以作用于类型的定义
也可以作用于方法的定义
T实现ICpmparable<T>接口
string类型的比较
T必须是值类型,且不能是可空的值类型-T必须是不可空的值类型
这个类型代表可空的类型
???
T有1个无参的构造函数-可以new T();
泛型类型内有1个泛型方法
U继承于T
泛型类型的子类
在子类里,可以继续让父类的类型参数保持开放
在子类里,也可以使用具体的类型来关闭父类的类型参数
子类也可以引入新的类型参数
子类先把父类的类型参数给关闭了然后又打开了
所以泛型类型的子类在继承时可以改类型参数的名字
自引用的泛型声明
针对每1个封闭类型,静态数据是唯一的
C#转换:
1.数值转换
2.引用转换
3.装箱拆箱转换
4.自定义转换
泛型转换时,发生的是哪种转换由已知类型的操作数来决定
T没有被特化
此时的引用转换会被错,编译不通过
将强转替换为as然后if判断是否为null,就不会编译报错
也可以将它先转换为Object然后再强转-引用转换
拆箱时也会有歧义
数值转换or拆箱操作or自定义转换-二义性-编译器直接报错
先转为Object再强转-确定是拆箱操作-编译器就不会报错了
covariance 协变
编译报错
无法隐式的将IList<string>转换为IList<object>-因为这个操作不安全
IEnumerable<out T>
T只作为返回类型
IList<T>实现了IEnumerable<T>接口
IList<T>
T既作为输入又作为输出
Action<T>
T只能作为输入
string继承于object
所以string可以向上转换为object
convariance协变-out-当值作为返回值输出-IEnumerable
contravariance逆变-in-当值作为输入-Action
invariance不变-in+out-当值既是输入又是输出-IList
variance只能出现在接口和委托里
variance转换是引用转换的1个例子
引用转换-无法改变其底层的值,只能改变变量编译时类型
identity conversion本体转换???
CLR层面,C#层面
C#:string->string
CLR-本体转换
object->dynamic
C#-不同类型
CLR-本体转换
3个例子都是隐式引用转换
1-C#类型系统是单根的,任何类型的父类都是object
2-string实现了IConvertible接口
3-从任何类型转换为object/dynamic类型都会发送隐式引用转换
1.必须要显式装换
2.二者无关
3.是隐式转换,但是是1个装箱操作,不是引用转换
4.数值转换
字符串数组
LINQ配合lambda使用
LINQ-Where-将长度大于1的过滤出来
List<string>->List<object>//编译报错
List是"不变"的
解决方法1:使用Cast方法
解决方法2:ToList<object>
发生了协变从IEnumerable<string>转换到了IEnumerable<object>
C#这种合成发生在运行时
C++发生在编译时,不可以被编译到dll里