1、泛型
泛型是framwork2.0推出的新语法,具有延迟声明的特点:把参数类型的声明推迟到调用的时候。泛型不是一个语法糖,是框架升级提供的功能。需要编辑器和JIT(just-in-time compilation、即时编译)的支持。
泛型并不存在性能问题,因为编译器支持 ,在即时编译的时候,编译器会生成一个泛型方法的副本,基本上和固定类型的方法性能无差别。
泛型的用处就是 用一个类、方法、接口、委托来满足不同的具体类型,然后做一样的事情。
泛型的约束有以下几种类型:
- 基类约束
- 接口约束
- 引用类型约束
- 值类型约束
- 无参数构造函数约束
约束必须是接口、非密封类(密封类无法被继承,不存在子类,所以约束没有意义)、类型参数;
约束可叠加,
泛型约束主要是用来保证代码安全。
2、协变逆变
这里用代码来解释一下这两个概念
1 using System; 2 using System.Collections.Generic; 3 4 namespace Util_YCH.Build.泛型 5 { 6 /// <summary> 7 /// 协变实例 8 /// </summary> 9 /// <typeparam name="T"></typeparam> 10 public interface IListAnimals<out T> { 11 /// <summary> 12 /// T只能作为返回值不能作为入参 13 /// </summary> 14 /// <returns></returns> 15 T GetT(); 16 /// <summary> 17 /// 所以这里会编译报错 18 /// </summary> 19 /// <param name="t"></param> 20 void setT(T t); 21 } 22 public class ListAnimals<T> : IListAnimals<T> 23 { 24 T t; 25 public T GetT() 26 { 27 throw new NotImplementedException(); 28 } 29 30 public void setT(T t) 31 { } 32 } 33 /// <summary> 34 /// 逆变实例 35 /// </summary> 36 /// <typeparam name="T"></typeparam> 37 public interface IListDogs<in T> 38 { 39 /// <summary> 40 /// T只能作为入参不能作为返回值 41 /// </summary> 42 /// <param name="t"></param> 43 void setT(T t); 44 /// <summary> 45 /// T无法作为返回值,此处会编译报错 46 /// </summary> 47 /// <returns></returns> 48 T GetT(); 49 50 } 51 public class ListDogs<T> : IListDogs<T> 52 { 53 public T GetT() 54 { 55 throw new NotImplementedException(); 56 } 57 58 public void setT(T t) 59 { 60 throw new NotImplementedException(); 61 } 62 } 63 /// <summary> 64 /// 动物类 65 /// </summary> 66 public class Animal 67 { 68 } 69 /// <summary> 70 /// 狗类 71 /// </summary> 72 public class Dog : Animal 73 { 74 } 75 76 public class Test { 77 public Test(){ 78 79 Animal animal1 = new Animal(); 80 Dog dog = new Dog(); 81 Animal animal2 = new Dog();//狗是动物 82 List<Animal> animals = new List<Dog>(); 83 //按照常规而言,Dog是Animal的子类,这样写应该是没有问题的,凡是编译器报错, 84 //原因是因为Dog是Animal的子类,但是List<Dog> 与 List<Animal> 之间不存在继承关系, 85 //于是为了消除这个BUG,就有了【协变】的概念 86 #region 协变 87 IListAnimals<Animal> listAnimals = new ListAnimals<Dog>(); 88 #endregion 89 #region 逆变 90 IListDogs<Dog> listAnimals2 = new ListDogs<Animal>(); 91 #endregion 92 } 93 94 } 95 }
3、泛型缓存
由于CLR会针对不同的类型会生成一个副本,所以可以实现泛型的缓存,示例代码如下
1 using System; 2 3 namespace Util_YCH.Build.泛型 4 { 5 /// <summary> 6 /// 每个不同的类型T都会生成一个副本, 7 /// 根据C#语言特性,静态字段和方法会在程序第一次运行的时候执行,缓存效率远远高于字典等缓存。 8 /// </summary> 9 public class Cache<T> 10 { 11 public Cache() 12 { 13 CacheStr = DateTime.Now.ToString(); 14 } 15 private static string CacheStr = ""; 16 public static string GetCacheStr() { 17 return CacheStr; 18 } 19 } 20 21 public class Test { 22 public Test(){ 23 24 #region 泛型缓存 25 var cache1 = new Cache<int>(); 26 var cache2 = new Cache<string>(); 27 var cache3 = new Cache<DateTime>(); 28 var cache4 = new Cache<double>(); 29 var cache5 = new Cache<bool>(); 30 #endregion 31 32 var cache11 = Cache<int>.GetCacheStr(); 33 var cache12 = Cache<int>.GetCacheStr(); 34 Console.WriteLine(cache11 == cache12); 35 Console.ReadKey(); 36 } 37 38 } 39 }
字典缓存是哈希结构的,读取缓存的时候需要进行查找,会消耗一定的资源;而泛型缓存的副本存在于内存里面,查找起来速度极快,但是有局限性,就是和类型相关,具有一定的限制。
这里的应用场景我能想到的就是可以针对每个实体缓存CRUD的Sql语句。