泛 型

一、泛型


1.引入泛型

假如一个方法,让这个方法既能接收int也能接收string、DateTime等,该如何做到呢?
在.net 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是引用类型,传入一个值类型,会有装箱,拆箱

栈->堆  装箱
堆->栈  拆箱
且类型不安全
值类型作为方法中的局部变量时,在栈中分配,而作为类的成员变量时,在堆中分配;
引用类型变量在栈中分配,引用类型的实例在堆中分配
(引用类型变量好比一个指针,它所指向的内容即引用类型的实例)

为了解决这些问题,在.net 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];
            }
      }

回到目录↩

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值