协变和逆变

概念

协变:以out修饰的泛型类型叫做协变类型,协变只能返回(当返回值),用于返回参数,协变T只能用来当返回值使用

逆变:以in修饰的泛型类型叫做逆变类型,逆变只能当参数传进来,用于接收参数,逆变T只能用来当参数传递

协变和逆变都是单向的。in可读不可写,out可写不可读

创建两个类,基类:Person,子类:Student

public class Person
    {
        public int Id { get; set; }
        public string UserName { get; set; }

    }

    public class Student : Person
    {

    }

协变

我们发现,如下代码会报错,虽然里氏转换子类可以给父类,但是这里不行,因为List 不继承List
List<Person> persons = new List<Student>();

但是,这样就可以,因为List实现了IEnumerable接口,也就是继承了IEnumerable,根据里氏转换,可以将子类赋值给父类,而且IEnumerable里的Person也是List()里Student的基类。
IEnumerable<Person> persons = new List<Student>();

原理是因为IEnumerable本身就是协变,它里面的泛型用out进行修饰了。
协变和逆变

协变:父类接收子类

我们模仿IEnumerable接口做个测试。,创建一个协变接口和实现这个接口

  //协变接口
    public interface IMyOut<out T>
    {
        T GetT();
    }

    //实现协变接口
    public class MyOut<T> : IMyOut<T>
    {
        public T GetT()
        {
            return default(T);
        }
    }

再Main里调用发现没问题

 IMyOut<Person> persons = new MyOut<Student>();
            persons.GetT();

协变和逆变


逆变:子类接收父类

//逆变接口
    public interface IMyIn<in T>
    {
        void GetT(T t);
    }

    //实现逆变接口
    public class MyIn<T> : IMyIn<T>
    {
        public void GetT(T t)
        {

        }
    }
IMyIn<Student> students = new MyIn<Person>();
            students.GetT(
                new Student()
                {
                    Id = 1,
                    UserName = "张三"
                });
	
上一篇:C#基础知识系列九(对IEnumerable和IEnumerator接口的糊涂认识)


下一篇:.NET(C#)判断泛型类型(List<>)和泛型接口(IEnumerable<>)的继承关系代码