美文网首页
C# 泛型的原理、引入、缓存、约束及泛型的“协变”和“逆变”

C# 泛型的原理、引入、缓存、约束及泛型的“协变”和“逆变”

作者: 浅谈码生活 | 来源:发表于2020-08-17 11:31 被阅读0次

    1.什么是泛型?

    就是在声明的时候,带上一个<>,指定类型参数,调用的时候指定类型调用。泛型可以有“泛型方法”,“泛型类”,“泛型接口”,“泛型委托”。

    2.泛型的原理:

    编译.png

    1.)泛型在编译之后,泛型参数会生成占位符`;
    2.)“CLR\JIT”根据不同的调用,生成不同的普通方法;
    3.)泛型不是语法糖,是框架的升级所支持的;

    3.泛型缓存:

    泛型缓存本质是一个泛型类,泛型类会根据调用的不同类型生成不同的副本;

     public class GenericCache<T>
    {
            static GenericCache()
            {
                Console.WriteLine("This is GenericCache 静态构造函数");
                _TypeTime = $"{typeof(T).FullName}_{DateTime.Now.ToString("yyyyMMddHHmmss.fff")}";
            } 
            private static string _TypeTime = ""; 
            public static string GetCache()
            {
                return _TypeTime;
            } 
     }
    

    4.泛型的约束:

    约束可分为:基类约束,接口约束,引用类型约束,值类型约束,无参数构造函数约束。

    //基类约束
     public static void Show<T>(T tParameter)
                where T : BaseClasee{}
    //接口约束
     public static void Show<T>(T tParameter)
                where T : ISports{}
    //引用类型约束
     public static void Show<T>(T tParameter)
                where T : class{}
    //值类型约束
     public static void Show<T>(T tParameter)
                where T : struct{}
    //无参数构造函数约束
     public static void Show<T>(T tParameter)
                where T : new(){}
    

    5.泛型的协变和逆变:

    为了架构层面上可能会产生类型安全的问题,所以引入协变和逆变。
    协变: Out 只能做返回值 ,不能做参数,其实是一种为了避开风险而存在的一种约束;

       public interface ICustomerListOut<out T>
        {
            T Get(); 
        }
      public class CustomerListOut<T> : ICustomerListOut<T>
        {
            public T Get()
            {
                return default(T);
            } 
        }
    

    逆变:In 只能做参数 ,不能做返回值,其实是一种为了避开风险而存在的一种约束;

      public interface ICustomerListIn<in T>
        {
            void Show(T t);
        }
        public class CustomerListIn<T> : ICustomerListIn<T>
        { 
            public void Show(T t)
            { 
            }
        }
    

    为了更好理解“协变”和“逆变”,我们首先定义两个类分别为父类Animal及子类Cat;

    //父类接口初始化子类实例时,父类对象无法调用子类方法所以T只能为返回值不能为参数称之为协变
    ICustomerListOut<Animal> customerList2 = new CustomerListOut<Cat>(); 
    //子类接口初始化父类实例时,子类对象可以调用父类方法但返回对象未必为父类所以T只能为参数不能为返回值称之为逆变
    ICustomerListIn<Cat> customerList1 = new CustomerListIn<Animal>();
    

    以上“协变”,“逆变”为个人理解,大家有不同的理解可以评论区留言相互探讨;

    相关文章

      网友评论

          本文标题:C# 泛型的原理、引入、缓存、约束及泛型的“协变”和“逆变”

          本文链接:https://www.haomeiwen.com/subject/bwktjktx.html