zoukankan      html  css  js  c++  java
  • C#进阶之泛型(Generic)

    1、泛型

    泛型是framwork2.0推出的新语法,具有延迟声明的特点:把参数类型的声明推迟到调用的时候。泛型不是一个语法糖,是框架升级提供的功能。需要编辑器和JIT(just-in-time compilation、即时编译)的支持。

    泛型并不存在性能问题,因为编译器支持 ,在即时编译的时候,编译器会生成一个泛型方法的副本,基本上和固定类型的方法性能无差别。

    泛型的用处就是 用一个类、方法、接口、委托来满足不同的具体类型,然后做一样的事情。

    泛型的约束有以下几种类型:

    1. 基类约束
    2. 接口约束
    3. 引用类型约束
    4. 值类型约束
    5. 无参数构造函数约束

    约束必须是接口、非密封类(密封类无法被继承,不存在子类,所以约束没有意义)、类型参数;

    约束可叠加,

    泛型约束主要是用来保证代码安全。

      

    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语句。

  • 相关阅读:
    预备作业02 : 体会做中学(Learning By Doing)
    7-1 货币转换
    秋季学校总结
    人生路上对我影响最大的三个老师
    自我介绍
    2019寒假作业3(抓老鼠啊~亏了还是赚了?)编程总结
    人生路上对我影响最大的三位老师
    自我介绍
    秋季学期学习总结
    7-1 抓老鼠啊~亏了还是赚了?
  • 原文地址:https://www.cnblogs.com/yuchenghao/p/12089288.html
Copyright © 2011-2022 走看看