泛 型

编程入门 行业动态 更新时间:2024-10-07 09:17:49

泛 型

泛 型

泛型

  • 一、泛型
    • 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.Dictionary2[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];}}

回到目录↩

更多推荐

泛 型

本文发布于:2024-03-12 13:23:43,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1731613.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!