泛 型
泛型
- 一、泛型
- 1.引入泛型
- 2.如何声明和使用泛型
- 3.泛型的好处和原理:延迟声明
- 4.泛型约束
- 5.协变、逆变
- 6.泛型缓存
- 回到目录↩
一、泛型
1.引入泛型
假如一个方法,让这个方法既能接收int也能接收string、DateTime等,该如何做到呢?
在 framwork 1.0的时候,我们可以使用object类型来完成:
ShowObject(1);//int
ShowObject("2");//string
ShowObject(DateTime.Now);
public static void ShowObject(Object oParameter)
{Console.WriteLine($"Type={oParameter.GetType().Name},Parameter={oParameter}");
}
Object:
1.Object类型是一切类型的父类
2.通过继承,子类拥有父类的一切属性和行为;任何父类出现的地方,都可以用子类来代替。
但是object是引用类型,传入一个值类型,会有装箱,拆箱
栈->堆 装箱
堆->栈 拆箱
且类型不安全
值类型作为方法中的局部变量时,在栈中分配,而作为类的成员变量时,在堆中分配;
引用类型变量在栈中分配,引用类型的实例在堆中分配
(引用类型变量好比一个指针,它所指向的内容即引用类型的实例)
为了解决这些问题,在 framwork 2.0,推出了泛型。
2.如何声明和使用泛型
//泛型方法T tNew = new T();public static void show<T>(T per){Console.WriteLine(per_T);}
//泛型类
public class TClass<T>
{public T _T;
}
TClass<int> tClass=new TClass<int>();
//泛型接口
public interface Gen<T>
{T GetT(T t);
}
public class GenX : Gen<int>
{public int GetT(int t){throw new NotImplementedException();}
}
public class GenY<T> : Gen<T>
{public T GetT(T t){throw new NotImplementedException();}
}
//泛型委托
public delegate void SayH<T>(T t);
3.泛型的好处和原理:延迟声明
泛型:
1.解决用一个方法,满足不同参数类型,做相同的事;
2.类型可以自动推算;
3.类型必须保持一致;
4.编译时没有写死参数类型,调用才指定类型,称为延迟声明;
4.1延迟声明:把参数类型的声明推迟到调用(推迟一切可以推迟的,延迟思想)
例如:惰性加载网页 数据库等到所有过滤条件准备好在过滤 抢票网站,推迟任务
不是语法糖,需要编译器支持+JIT支持
编译器---------[]--------------->exe-------------->运行环境CLR里面的(JIT)[]-------------->机器码
-------- 泛型在[]产生占位符-----------------------------[]填入相关类型
//占位符验证
Console.WriteLine(typeof(List<>));
Console.WriteLine(typeof(Dictionary<,>));
System.Collections.Generic.List1[T] System.Collections.Generic.Dictionary
2[TKey,TValue]
4.泛型约束
T tNew = new T();public static void show<T>(T per)where T:TClass<int>{Console.WriteLine(per_T);}
泛型约束(基类约束):where T:People 不能是Sealed密封类
1.可以使用基类的一切属性方法
2.强制保证T一定是Prople或其子类
where T: Gen//接口约束
where T:calss//引用类型约束
where T:struct//值类型约束
T tName=default(T);//会根据T的不同,赋予默认值
where T:new()//无参数构造约束
不能用基类,int 这种不行
约束可以叠加,更灵活
where T:Prope,IsSports,IWork,new()
5.协变、逆变
public class Bird {public int Id { get; set; }}public class Sparrow : Bird {public string Name { get; set; }}public static void Show() {{Bird bird1 = new Bird();Bird bird2 = new Sparrow();}{List<Bird> birds = new List<Bird>();//**********************************************************//List<Bird> birds1 = new List<Sparrow>();//List<Sparrow>不能付给List<Bird>,没有父子关系Brid与Sparrow有//为了解决这个问题,提出了协变,逆变//List<Bird> -----> List<Sparrow>() 协变//List<Sparrow> -----> List<Bird>() 逆变//**********************************************************List<Bird> birds2 = new List<Sparrow>().Select(c => (Bird)c).ToList();}{//协变//用于接口或者委托IEnumerable<Bird> birds = new List<Bird>();IEnumerable<Bird> birds1 = new List<Sparrow>();Func<Bird> func = new Func<Sparrow>(()=>null);}{//自定义协变ICustomerListOut<Bird> birds = new CustomerListOut<Bird>();ICustomerListOut<Bird> birds1 = new CustomerListOut<Sparrow>();}{//逆变ICustomerListIn<Sparrow> birds = new CustomerListIn<Sparrow>(); ICustomerListIn<Sparrow> birds1 = new CustomerListIn<Bird>();}{IMyList<Sparrow, Bird> myList = new MyList<Sparrow, Bird>();IMyList<Sparrow, Bird> myList1 = new MyList<Sparrow, Sparrow>();//协变IMyList<Sparrow, Bird> myList2 = new MyList<Bird, Bird>();//逆变IMyList<Sparrow, Bird> myList3 = new MyList<Bird, Sparrow>();//逆变+协变}}//协变的接口 只能是返回结果public interface ICustomerListOut<out T>{T Get();}public class CustomerListOut<T> : ICustomerListOut<T>{public T Get(){return default(T);}}//逆变 只能当参数,不能做返回值public interface ICustomerListIn<in T> {void Show(T t);}public class CustomerListIn<T> : ICustomerListIn<T>{public void Show(T t){;}}//协变+逆变public interface IMyList<in inT, out outT> {void Show(inT T);outT Get();outT Do(inT t);}public class MyList<T1, T2> : IMyList<T1, T2>{public T2 Do(T1 t){Console.WriteLine(t.GetType().Name);Console.WriteLine(typeof(T2).Name);return default(T2);}public T2 Get(){Console.WriteLine(typeof(T2).Name);return default(T2);}public void Show(T1 T){Console.WriteLine(T.GetType().Name);}}
6.泛型缓存
//不同的T,都会生成一份不同的副本//适合不同的类型,需要缓存一份数据的场景,效率高public class GenericCache<T> {static GenericCache() //静态字段--静态构造{Console.WriteLine();_TypeTime = string.Format("{0}_{1}", typeof(T).FullName, DateTime.Now.ToString());}private static string _TypeTime = "";public static string GetCache() {return _TypeTime;}}//都会重新构造,在调用一次就不回来public static void Show2(){for (int i = 0; i < 5; i++) {Console.WriteLine(GenericCache<int>.GetCache());//泛型的缓存Thread.Sleep(10);Console.WriteLine(GenericCache<long>.GetCache());Thread.Sleep(10);Console.WriteLine(GenericCache<string>.GetCache());Thread.Sleep(10);}}
静态字典 与泛型相比,由于Key 要哈希,在查找,比泛型要慢
public class DictionaryCache //静态字典{private static Dictionary<Type, string> keyValuePairs = null;static DictionaryCache() {keyValuePairs = new Dictionary<Type, string>();}public static string GetCache<T>(){Type type=typeof(Type);if (!keyValuePairs.ContainsKey(type)) {keyValuePairs[type] = string.Format("{0}_{1}", typeof(T).FullName, DateTime.Now.ToString());}return keyValuePairs[type];}}
回到目录↩
更多推荐
泛 型
发布评论