C#协变和逆变

CSDN代码 | GitHub代码
协变(covariant)和逆变(contravariant)是C#4.0新增的概念。

协变
首先,我们都知道C#中父类可以充当子类来使用,就像我们在泛型中说到的object是所有类型的父类,那么以下变量赋值时不会报错:

string str = string.Empty;
object obj = str;

如果换一种方式来表达:
创建一个Human类:

using System;
using System.Collections.Generic;

namespace GenericPracitce
{
    public class Human
    {
      public string name { get; set; }
    }
}

创建一个子类Chinese:

using System;
using System.Collections.Generic;

namespace GenericPracitce
{
    public class Chinese:Human
    {
      public string age { get; set; }
    }
}

在Main()方法中调用:

using System;
using System.Collections.Generic;

namespace GenericPracitce
{
    public class Program 
    {
    	static void Main(string[] args)
    	{
    		//声明Human,和Chinese类,不会有问题
    		Human human = new Human();
    		Chinese chinese = new Chinese();
    		//Chinese是Human的子类,所以声明不会有问题
			Human shuman = new Chinese();
			
			//声明List
			List<Human> listHuman = new List<Human>();
			List<Chinese> listChinese = new List<Chinese>();
			//在这里,会出现错误
			List<Human> list = new List<Chinese>();
		}
    }
}

这里的Human虽然是Chinese的父类,但是如果将Human,和Chinese当做List类型来用,那么这里的2个List就不再有继承关系。没有继承关系在声明的时候就会出错。
在这里插入图片描述
这时候就需要使用协变:

IEnumerable<Human> List1 = new List<Chinese>();

查看IEnumerable定义:
在这里插入图片描述
可以看到协变类似于一个泛型接口,但是不同的是在泛型接口的T前面有一个out关键字修饰(这里的out不是ref的那个out),这就是协变,协变的定义为左边声明的是基类,右边可以声明基类以及基类的子类。协变可以直白的理解为string->object,out关键字可以单纯的理解为输出,作为返回值

根据协变的规则,也可以自定义协变:

using System;

namespace GenericPracitce
{
    public interface ICustomCovariant<out T>
    {
        T Get();
    }

    public class CustomCovariant<T>:ICustomCovariant<T>
    {
        public T Get()
        {
            return default(T);
        }
    }
}
=========================================================================
//Main调用
ICustomCovariant<Human> custom = new CustomCovariant<Chinese>();

逆变
逆变可以直白的看为object->string,协变的关键字是out,逆变的关键字是in,在你变种in只能作为传入值不能作为返回值。

using System;

namespace GenericPracitce
{
    public interface ICustomContravariant<in T>
    {
        void Get(T t);
    }

    public class CustomContravariant<T>:ICustomContravariant<T>
    {
        public void Get(T t)
        {
        }
    }
}
=========================================================================
//Main调用
ICustomContravariant<Chinese> custom = new CustomContravariant<Human>();

我们可以看出协变和逆变是相反的协变可以看作string->object,逆变可以看作object->string。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值