1:什么是泛型与泛型使用加协变逆变

1. 什么是泛型?

就在在声明的时候,带上一个<>,指定类型参数,调用的时候指定类型调用---泛型;

概念

可直接跳过的概念。

  1. 泛型方法:一个方法满足了不同类型的需求;

  2. 泛型类:一个类满足不同类的需求;

  3. 泛型接口:一个接口满足不同接口的需求;

  4. 泛型委托:一个委托满足不同委托的需求;

    Object是一切类型的父类。
    任何父类出现的地方都可以用子类来代替。

举例

下面代码段,这就是常用的泛型<>;就是说在传类型以前他可以是任何类型。传int或类等类或结构类型的时候就限定了他的类型。
List<int> intlist = new List<int>();
List<string> stringlist = new List<string>();

2. 如何声明和使用泛型?

代码示例与效果

public class Monitor
    {
    
    
        public static void Show()
        {
    
    
            Show<int>(1);
        }
        private static void Show<T>(T tParameter)
        {
    
    
            Console.WriteLine($"调用第一次泛型{tParameter}");
        }
    }

代码执行图

3. 泛型的延迟思想?

尽量靠后实现具体

写代码时尽可能把实际的实现内容往后靠,这样一个朦胧的程序使我们有了多种可能。比如就可以在我们在调用的时候再约定它该是一个什么参数。

4. 泛型的好处和原理?

好处

  1. 一个方法可以满足不同类型的需求。(某个类中需要传参数,int,string等,不能每个不同类型参数要新写一个方法。无法实现高可用与可扩展,那么就可以用到泛型。当然此处也可使用Object但是速度会慢两倍之多,因为涉及到装箱拆箱)
    装箱 就是把“值类型”转换成“引用类型”(Object);
    拆箱 就是把“引用类型”转换成“值类型”;
  2. 性能高(他的速度和直接使用int,string等结构或类时速度一样)。

原理与概念

泛型在编译之后,泛型参数会生成占位符2
最终会根据调用生成不同的普通方法;
泛型在.NetFramework2已经出来了;
泛型不是一个语法糖(语法糖指添加某种语法,对语言的功能并没有影响,方便程序员使用);
泛型—编译器升级+CLR升级
泛型是框架的升级所支持的;

5. 泛型类、方法、接口、委托?

概念

  1. 泛型方法:一个方法满足了不同类型的需求;
  2. 泛型类:一个类满足不同类的需求;
  3. 泛型接口:一个接口满足不同接口的需求;
  4. 泛型委托:一个委托满足不同委托的需求;

6. 泛型约束,泛型缓存?

约束解决什么

传入的参数在处理的时候,可能会出现真实类型不匹配的情况。

泛型约束分类

  1. 基类约束:约束这个T 就是People; 就约束只能传递People或者People的子类
  2. 接口约束:约束这个T 是ISports接口的实现类 可以调用接口中的方法—权利;调用的时候–只能传递实现过这个接口的类进入–义务
  3. 引用类型约束:只能传入引用类型的参数
  4. 值类型约束:只能传入值类型的参数
  5. 无参数构造函数约束:传入的参数必须有拥有一个无参数构造函数只需要在限定类型处写:new()

约束如何写

通过观察如下代码段。仅需要在参数后增加
where T(参数类型):(限定类型)
限定类型可以为

		/// <summary>
        /// 值类型约束
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="tParameter"></param>
        public static T ShowStruct<T>(T tParameter)
          where T : struct
        {
    
    
            return default(T);  //任何类型都可以,default(T) 根据实际的调用类来生成默认值;
        }
         
        /// <summary>
        ///引用类型约束
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="tParameter"></param>
        public static T ShowClass<T>(T tParameter)
          where T : class
        {
    
    
            return default(T);  //任何类型都可以,default(T) 根据实际的调用类来生成默认值;
        }

约束

缓存应用场景

举例子:比如要进行根据实体类获取增删改查语句。这时候就可以用到缓存放起来。
/// <summary>
    /// 字典缓存:静态属性常驻内存
    /// </summary>
    public class DictionaryCache
    {
    
    
        private static Dictionary<Type, string> _TypeTimeDictionary = null;
        static DictionaryCache()
        {
    
    
            Console.WriteLine("This is DictionaryCache 静态构造函数");
            _TypeTimeDictionary = new Dictionary<Type, string>();
        }
        public static string GetCache<T>()
        {
    
    
            Type type = typeof(T);
            if (!_TypeTimeDictionary.ContainsKey(type))
            {
    
    
                //_TypeTimeDictionary[type] = string.Format("{0}_{1}", typeof(T).FullName, DateTime.Now.ToString("yyyyMMddHHmmss.fff"));  
                _TypeTimeDictionary[type] = $"{typeof(T).FullName}_{DateTime.Now.ToString("yyyyMMddHHmmss.fff")}";
            }
            return _TypeTimeDictionary[type];
        }
    }

7. 协变逆变?

概念

协变 协变: Out 只能做返回值 ,不能做参数,可以让右边使用子类
逆变 逆变: in 只能做参数 ,不能做返回值,可以让右边使用父类

使用

如下代码块会出错,因为我们指定泛型的类型为Animal,实例的时候传入Cat就会出错。
注:Cat是继承自Animal

	
    #region 协变  逆变例子
    /// <summary>
    /// T 就只能做参数  不能做返回值
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public interface ICustomerListIn<in T>
    {
    
    
       //T Get();
        void Show(T t);
    }

    public class CustomerListIn<T> : ICustomerListIn<T>
    {
    
    
        //public T Get()
        //{
    
    
        //    return default(T);
        //}
        public void Show(T t)
        {
    
    

        }
    }

    /// <summary>
    /// out 协变 只能是返回结果 
    /// 泛型T 就只能做返回值; 不能做参数; 
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public interface ICustomerListOut<out T>
    {
    
    
        T Get();
       //void Show(T t); 
    }

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

        //public void Show(T t)
        //{
    
    

        //}
    }

    public interface IMyList<in inT, out outT>
    {
    
    
        void Show(inT t);
        outT Get();
        outT Do(inT t);

        out 只能是返回值   in只能是参数
        //void Show1(outT t);//左边声明是父类---右边实例化是子类 new MyList<Cat, Cat>()---outT是cat--方法调用时以左边为准,传递的是animal的子类-狗
        //inT Get1(); 
    }

    /// <summary>
    /// out 协变 只能是返回结果 
    /// in  逆变 只能是参数
    /// 
    /// </summary>
    /// <typeparam name="T1"></typeparam>
    /// <typeparam name="T2"></typeparam>

    public class MyList<T1, T2> : IMyList<T1, T2>
    {
    
    
        public void Show(T1 t)
        {
    
    
            Console.WriteLine(t.GetType().Name);
        }

        public T2 Get()
        {
    
    
            Console.WriteLine(typeof(T2).Name);
            return default(T2);
        }

        public T2 Do(T1 t)
        {
    
    
            Console.WriteLine(t.GetType().Name);
            Console.WriteLine(typeof(T2).Name);
            return default(T2);
        }
    }
    #endregion

8. 意外收获?

收获

哈哈哈哈,新学到一个拼字符串的方式。
在拼接字符串的最前加$中间需要加什么参数打一个{}在里边放参数就可以了

Console.WriteLine($"调用第一次泛型{tParameter}");

猜你喜欢

转载自blog.csdn.net/hello_mr_anan/article/details/107444182