zoukankan      html  css  js  c++  java
  • .net(一) 泛型generic使用和原理 封装泛型缓存

    点击返回  .net 初级高级 武林秘籍内功

    大纲:

    1.泛型的由来: CLR+JIT  延迟申明

    2.泛型与object的对比、代码举例

    3.泛型类、泛型方法、泛型接口、泛型委托

    4.泛型约束

    5.泛型的协变逆变

    1.泛型的由来: CLR+JIT  延迟申明

    泛型基本概念:.NET 泛型是一个很强大的新特性,它为每一种对象生成一份单独的代码(也就是所谓的“实例化”),这一份量身顶做的代码具有很高的效率,是强类型的,不需要运行期多态的支持和负担,有了泛型,就不再需要Object类来参与实现一些通用类或方法了.

    泛型的作用: 在CLR(common language runtime)1.0中,当要创建一个灵活的类或方法,但该类或方法在编译期问不知道使用什么类,就必须以System.Object类为基础进行处理,而Object类在编译期间没有类型安全性,又必须进行强制类型转换.另外,给值类型使用Object类会有性能损失,这给程序开发带来诸多不便.故在CLR 2.0(.NET 3.5基于CLR 2.0)中,提供了泛型.

    通过使用泛型类型,可以根据需要,用特定的类型替换泛型类型,同时保证了类型安全性:如果某个类型不支持泛型类,编译器就会报错,以阻止程度发生运行期错误.正确使用泛型将大大提高代码的灵活性,结合一个优秀的设计模式,可以显著缩短开发时间.
    总而言之:泛型,其实就是 CLR+JIT的支持,使用泛型,可以重用代码,由CLR+JIT延迟等编译和执行的时候生成一个个具体的类或方法等等 的副本。比如:public class A<T>类,这样,我new的时候,var aStr= new A<string>();var aInt=new A<int>();这样,其实在编译的时候,会生成 A_001(string) 类和A_002 (int)类。 
     
     
     2.泛型与object的对比、代码举例
    以上要是看的不是很懂的,例子来了。
    比如我们需要打印出,传入参数的类型名称,那么使用常规代码方式,有常用2种方式去实现:
    第一种,调用对应的showInt(),showString(),showTime().........方法,如下:
    常规代码使用(令狐冲练的武功就是这样的):
    /// <summary>
    /// 打印个int值 
    /// </summary>
    /// <param name="iParameter"></param>
    public static void ShowInt(int iParameter)
    {
        Console.WriteLine("This is {0},parameter={1},type={2}",
            typeof(CommonMethod).Name, iParameter.GetType().Name, iParameter);
    }
    /// <summary>
    /// 打印个string值
    /// </summary>
    /// <param name="sParameter"></param>
    public static void ShowString(string sParameter)
    {
        Console.WriteLine("This is {0},parameter={1},type={2}",
            typeof(CommonMethod).Name, sParameter.GetType().Name, sParameter);
    }
    /// <summary>
    /// 打印个DateTime值
    /// </summary>
    /// <param name="oParameter"></param>
    public static void ShowDateTime(DateTime dtParameter)
    {
        Console.WriteLine("This is {0},parameter={1},type={2}",
            typeof(CommonMethod).Name, dtParameter.GetType().Name, dtParameter);
    }
    //如果做数据库查询,每一个实体对应的表,那岂不是每一个实体都要写一个方法吗?
    看看调用:
    
    int iValue = 123;
    string sValue = "456";
    DateTime dtValue = DateTime.Now;
    object oValue = "789";
    
    ShowInt(iValue);
    ShowString(sValue);
    ShowDateTime(dtValue);
    常规代码使用
    第二种,使用showObject(object oParameter);
    使用object(岳不群自宫):
    /// <summary> 
    ///为什么用object 作为参数类型,调用的时候,可以把任何类型都传进来
    ///
    ///C#: 任何父类出现的地方  都可以用子类代替;
    ///Object类型是一切类型的父类
    ///
    ///Object 出现的都可以让任何类型传进来
    /// 
    /// 但是:有2个问题
    ///        性能问题:会出现装箱和拆箱;
    ///        类型安全问题。 
    /// </summary>
    /// <param name="oParameter"></param>
    public static void ShowObject(object oParameter)
    {
        Console.WriteLine("This is {0},parameter={1},type={2}",
            typeof(CommonMethod), oParameter.GetType().Name, oParameter);
    }
    
    看看调用:
    ShowInt(iValue);
    ShowString(sValue);
    ShowDateTime(dtValue);
    使用object
     泛型类使用(小林子的葵花宝典):
    /// <summary>
    /// 泛型方法:需要在方法名的后面带一个<>,需要定义T, T是什么呢? 不知道, 
    /// T:类型参数,只是一个占位符,类型在声明其实不确定,在调用的时候,确定类型。
    ///  
    /// 延迟声明,推迟一切可以推迟的,事情能晚点做就晚点做。 
    /// 在使用的时候,需要指定明确的类型
    /// 泛型方法性能和普通方法差不多,可以用一个方法满足多个类型的需求 
    /// 集成了前面2种的各自的长处。既可以安全调用,性能又好,并且可以用一个方法代替N个方法
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="tParameter"></param>
    public static void Show<T>(T tParameter)
    {
        Console.WriteLine("This is {0},parameter={1},type={2}",
            typeof(CommonMethod), tParameter.GetType().Name, tParameter);
    }
    
    看看调用:
    
    Show(iValue); //如果类型参数,可以通过参数类型推导出来,那么就可以省略
    /* Show<int>(sValue);*/// 因为类型错了 
    Show(sValue);
    Show<DateTime>(dtValue);
    Show<object>(oValue);
    使用泛型

     3.泛型类、泛型方法、泛型接口、泛型委托

    泛型方法 一个方法满足多个类型的需求
    泛型类 就是一个类 满足多个类型的需求
    泛型接口 就是一个接口 满足多个多个类型的需求
    泛型委托 就是一个委托 满足多个多个类型的需求

    a.泛型类:

    //泛型类的定义在常规的类后面加<T>,T为占位符,可以任何字符代替。
    //eg:  public class Student<T>{}
    //亦可以多个类型。占位符不重复,用逗号隔开
    //eg:  public class People<T,A,B,C>{}
    
    //例子a:
    public class ClassA<T>
    {
        /// <summary>
        /// 获取T的类型全名称
        /// </summary>
        /// <returns></returns>
        public string GetTTypeName()
        {
            return typeof(T).FullName;
        }
    }
    //使用
    //使用泛型来打印实例类型
    {
        ClassA<int> aInt = new ClassA<int>();
        Console.WriteLine(aInt.GetTTypeName());//System.Int32
    
        ClassA<string> aStr = new ClassA<string>();
        Console.WriteLine(aStr.GetTTypeName());//System.String
    
        Console.ReadLine();
    }
    
    //例子b:
    public class ClassB<T,A> 
        where T:struct  //约束T是个struct
        where A:class,new () //约束A是个引用类型,无参数构造函数约束
    {
        /// <summary>
        /// 获取T的类型全名称
        /// </summary>
        /// <returns></returns>
        public string GetTTypeName()
        {
            return typeof(T).FullName;
        }
    }
    泛型类

    b.泛型方法:

    例子在上面的2.“使用泛型”那有。

    c.泛型接口:

    //我们有4个类(人类、中国人、广东人、日本人),
    //中国人继承人类,广东人继承中国人。日本人没继承人类。
    //有2个接口(IWork,ISports)
    
    public interface ISports
    {
        void Pingpang();
    }
    
    public interface IWork
    {
        void Work();
    }
    
    /// <summary>
    /// 人类
    /// 基本属性有:ID,名称,会说Hi
    /// </summary>
    public class People
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public void Hi()
        { }
    }
    
    /// <summary>
    /// 中国人:继承了人类(拥有人类的基本属性)
    /// 也有自己的说Hi方式,有额外的属性,还实现了运动,工作
    /// </summary>
    public class Chinese : People, ISports, IWork
    {
        public void Tradition()
        {
            Console.WriteLine("仁义礼智信,温良恭俭让");
        }
        public void SayHi()
        {
            Console.WriteLine("吃了么?");
        }
        public void Pingpang()
        {
            Console.WriteLine("打乒乓球...");
        }
        public void Work()
        {
            Console.WriteLine("工作中...");
        }
    }
    
    /// <summary>
    /// 广东人:继承了中国人(拥有中国人的基本属性)
    /// 额外还会吃。
    /// </summary>
    public class GuangDong : Chinese {
        public void Eat()
        {
            Console.WriteLine("正在吃福建人...");
        }
    }
    
    /// <summary>
    /// 日本人:只实现了运动
    /// </summary>
    public class Japanese : ISports
    {
        public int Id { get; set; }
        public string Name { get; set; }
    
        public void Pingpang()
        {
            Console.WriteLine("雅美蝶,打乒乓球...");
        }
    }
    
    
    //如下调用
    People people = new People()
    {
        Id = 1,
        Name = "令狐冲"
    };
    Chinese chinese = new Chinese()
    {
        Id = 2,
        Name = "岳不群"
    };
    GuangDong guangDong = new GuangDong()
    {
        Id = 3,
        Name = "小林子"
    };
    Japanese japanese = new Japanese()
    {
        Id = 4,
        Name = "冲田杏梨"
    };
    
    //现在有这4个对象
    //我想要他们,统统运动起来,如下:
    //常规:
    // people 没有运动的方法
    chinese.Pingpang();
    guangDong.Pingpang();
    japanese.Pingpang();
    
    //如果,我想他们统统运动起来,使用把对象传入进去的方法,
    //那么又回到上面我说,替这3个类加3个方法
    /*eg:
     * public static void ChineseShowSports(Chinese chinese){ chinese.Pingpang(); }
     * public static void GuangDongShowSports(GuangDong guangDong){guangDong.Pingpang(); }
     * public static void JapaneseShowSports(Japanese japanese){japanese.Pingpang(); }
     */
     //调用如下
    ChineseShowSports(chinese);
    GuangDongShowSports(guangDong);
    JapaneseShowSports(japanese);
    
    
    //这样也是可以的,那么下面的泛型就可以把他们泛型成一个方法
    /*eg:
     * public static void ShowSports<T>(T t) where T: People,ISports
     * {
     *     t.Pingpang();
     * }
     */
    //调用如下
    ShowSports(chinese);
    ShowSports(guangDong);
    ShowSports(japanese);
    View Code

        

    从这俩张图可见,where T 起到了约束,所以可以使用里面的方法和属性。

    4.泛型约束

    在上面的代码中,可以看到一些泛型约束的使用了。

    泛型约束 是 在泛型类、方法、等对其调用的约束,起到保护作用和使用(履行义务+享受权利),使用方法是  后面跟 where T : Class,new()等。多重约束使用逗号隔开。

    多泛型如T,G,F,使用多个where。如:

    public static void ShowSports<T,G,F>(T t)
    
    where T :People,ISports
    
    where G:ISports
    
    where F:Class
    
    {
      //这里是业务,可以使用 T,G,F
    }
    View Code

    说明

    where T:People// 约束T是People类型

    where T:ISports// 约束T是实现ISports类型

    where T :Class// 约束T是引用类型
    where T :new()// 无参数构造的函数约束

    where T :struct// 约束T是结构类型

    举个例子

    我要这3个对象运动一下,要求是个人才能运动

    public static void ShowSportsByPeople<T>(T t) where T :People, ISports
    {
        t.Pingpang();
    }
    
    //调用
    ShowSportsByPeople(chinese);//打乒乓球...
    ShowSportsByPeople(guangDong);//打乒乓球...
    ShowSportsByPeople(japanese);//这个会报错,老师亚麻跌不出来
    //说明泛型约束,保证了调用安全。
    View Code

    5.泛型的协变逆变

    选修:in out

    哈哈,不说了

     

    点击返回  .net 初级高级 武林秘籍内功

  • 相关阅读:
    第十三周助教作业
    【西北师大-19软工】第五次作业成绩汇总
    第十二周助教工作总结
    第十一周助教工作总结
    第九周助教工作总结
    第八周助教工作总结
    第七周助教工作总结
    SQLAlchemy 学习笔记(二):ORM 基础
    WebSocket 与 HTTP/2
    Chrome 与 Firefox-Dev 的 DevTools
  • 原文地址:https://www.cnblogs.com/Bruke/p/12143639.html
Copyright © 2011-2022 走看看