【学习笔记】泛型

1、泛型类、泛型方法、泛型接口、泛型委托。

2、用到的设计思想:延迟声明(能推迟做的事情就尽量推迟做)。

3、语法糖:编译器自动帮我们识别类型,泛型不是简单的语法糖,它是框架升级和语法糖的双重结果。

4、泛型就是用一个东西来满足多种不同类型的需求的。

5、引入泛型前使用object作为类型参数有2个问题

  1)、装箱拆箱,性能损耗。传入一个int值(栈) ,object又在堆里面,如果把int传递进来,就会把值从栈里面copy到堆里(装箱)。使用的时候,又需要用对象值,又会copy到栈(拆箱)。

  2)、类型安全问题,可能会有,因为传递的对象是没有限制的。

6、泛型约束

/*
* 五种约束:
* 
* where T:struct  值类型约束:类型参数必须为值类型
* 
* where T:class   引用类型约束:适用于类、接口、委托、数组等,类型参数必须为引用类型
* 
* where T:new()   new()无参构造器约束:类型参数必须有一个公有的无参构造器
* 
* where T:   基类约束:类型参数必须是指定的基类或是派生自指定的基类
* 
* where T:   接口约束:类型参数必须是指定接口或实现指定的接口,可以指定多个接口约束,约束接口也可以是泛型的
* 
* 
* 组合约束:用的不多
* 在约束列表中,第一个必须是引用类型约束或者值类型约束,或者是基类约束,然后才是接口约束,最后才是new()约束
* 指定引用类型约束或值类型约束的同时也指定基类约束是非法的
* 
* 同一个类型形参可以使用多个约束,中间用逗号隔开,例如:
* class Test where T : Myclass, Interface, new(){......}
* 替换T的类型实参必须是继承Myclass类,且实现Interface接口,且拥有一个无参构造器
* 
* 在使用两个或多个类型形参时,也可以使用多条where子句分别为它们指定约束
*/

 下面通过一个简单的例子来看下如何使用

using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApp1
{
    /// 
    /// 泛型类
    /// 
    public class MyGeneric
        where T1 : Person, ISay //T1必须是Person类或者是Person的派生类,并且实现了ISay接口
        where T2 : ISky //T2必须是实现了ISky接口
    {
        public void Say(T1 t)
        {
            t.Say(t.Name);
        }

        public void Sky(T2 t)
        {
            t.Sky();
        }

        /// 
        /// 泛型方法
        /// 
        /// 
        /// 
        /// 
        public T3 GetDefault(T3 t)
            where T3 : struct
        {
            return default(T3);
        }
    }

    /// 
    /// 人类
    /// 
    public class Person
    {
        /// 
        /// 姓名
        /// 
        public string Name { get; set; }
    }

    /// 
    /// 说接口
    /// 
    public interface ISay
    {
        void Say(string name);
    }

    /// 
    /// 飞接口
    /// 
    public interface ISky
    {
        void Sky();
    }
}

7、协变和逆变

  1)、二者只使用与泛型委托和泛型接口。

  2)、协变:由子类方向 向 父类方向 转变,用out关键字,T类型只能用于返回值。

  3)、逆变:由父类方向 向 子类方向 转变,用in关键字,T类型只能用于传入参数。

using System;
using System.Collections.Generic;
using System.Linq;

namespace MyGeneric.Extend
{
    /// 
    /// 所谓协变逆变,都是跟泛型相关,
    /// 只能放在接口或者委托的泛型参数前面
    /// out 协变covariant    修饰返回值 
    /// in  逆变contravariant  修饰传入参数
    /// 
    public class CCTest
    {
        public static void Show()
        {
            //Func
            {
                Bird bird1 = new Bird();
                Bird bird2 = new Sparrow();//子类实例化 麻雀当然是个bird
                Sparrow sparrow1 = new Sparrow();
                //Sparrow sparrow2 = new Bird();//子类变量  不能用父类实例化
            }

            {
                List birdList1 = new List();
                //List birdList2 = new List();
                //一堆麻雀  难道不是  一堆鸟吗?  语义上是可以的
                //不成立,语法不通过,原因是List是一个类--List也是一个类,没有父子关系

                List birdList3 = new List().Select(c => (Bird)c).ToList();
            }

            //泛型还有不够和谐的地方---泛型不就是为了书写方便
            {
                //协变:就是让右边可以用子类,让泛型用起来更方便
                //out修饰,协变后,T只能作为返回值,不能当参数
                IEnumerable birdList1 = new List();
                IEnumerable birdList2 = new List();

                Func func = new Func(() => null);

                ICustomerListOut customerList1 = new CustomerListOut();
                ICustomerListOut customerList2 = new CustomerListOut();
                customerList2.Get();
            }

            {
                //逆变:就是让右边可以用父类,让泛型用起来更方便
                //in修饰,逆变后,T只能作为当参数  不能做返回值,
                ICustomerListIn customerList2 = new CustomerListIn();
                ICustomerListIn customerList1 = new CustomerListIn();
                customerList1.Show(new Sparrow());

                ICustomerListIn birdList1 = new CustomerListIn();
                birdList1.Show(new Sparrow());
                birdList1.Show(new Bird());

                Action act = new Action((Bird i) => { });
            }

            {
                IMyList myList1 = new MyList();
                IMyList myList2 = new MyList();//协变
                IMyList myList3 = new MyList();//逆变
                IMyList myList4 = new MyList();//协变+逆变
            }
        }
    }

    /// 
    ////// 
    public class Bird
    {
        public int Id { get; set; }
    }

    /// 
    /// 麻雀
    /// 
    public class Sparrow : Bird
    {
        public string Name { get; set; }
    }

    /// 
    /// 逆变
    /// 
    /// 
    public interface ICustomerListIn<in T>
    {
        //T Get();//不能做返回值

        void Show(T t);
    }

    public class CustomerListIn : ICustomerListIn
    {
        //public T Get()
        //{
        //    return default(T);
        //}

        public void Show(T t)
        {
        }
    }

    /// 
    /// out 协变 只能是返回结果,不能做参数
    /// 
    /// 
    public interface ICustomerListOut<out T>
    {
        T Get();

        //void Show(T t);
    }

    public class CustomerListOut : ICustomerListOut
    {
        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);
        //inT Get1();
    }

    public class MyList : IMyList
    {
        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);
        }
    }
}

 

你可能感兴趣的:(【学习笔记】泛型)