c# 逆变 协变的理解

逆变和协变是C# 4.0出来的,个人认为这是对泛型的扩充,让C#的语法更加灵活,方便重用。只有泛型接口和泛型委托可以是协变的或逆变的。

泛型中有out in关键字,用于定义此泛型是遵守逆变还是协变。out限制了泛型只能用于返回值,in限制了泛型只能用于参数。

之前的泛型是可以指定对某一类操作,但是无法把类的子类,父类赋值转换。有了逆变和协变,实现了泛型类的父类子类的转换。

协变 (covariant)关键字是out,out限制了泛型只能用于返回值

示例代码如:
public interface IEnumerable<out T>


public static void Main()

{

     Dog aDog = new Dog();

     Animal aAnimal = aDog;

     IEnumerable<Dog> someDogs = new List<Dog>();

     IEnumerable<Animal> someAnimals = someDogs;

}

现在我们有Animal父类,Dog, Cat子类

    public class Animal
    {
        public string type;

        public Animal()
        {
            type = "Animal";
        }
    }

    public class Dog : Animal
    {
        public Dog()
        {
            type = "dog";
        }
    }

    public class Cat : Animal
    {
        public Cat()
        {
            type = "Cat";
        }
    }
如果我们使用List<T>泛型,那我们在List<Animal>和List<Cat>是不能互相转换的。下面的代码是编译不通过的

List<Animal> animalList = new List<Dog>(); 
如果要实现这个转换必须要使用如下的方法

  animalList = dogList.Select(o => (Animal)o).ToList();

但现在我们有这样的方法

 public void PrintAnimals(IEnumerable<Animal> animals)
        {
            foreach (var item in animals)
            {
                Console.WriteLine(item.type);
            }
        }
就可以能传递List<Cat>了, 也能传递List<Animal>,因为IEnumerable<out T>有out标记,表示可以协变,所以编译通过。但是在内部,IL还是帮我做了一个个元素依次转换

的工作。这样可以减少了我们的代码量,让程序更灵活。


逆变(contravariant)关键字是in,in限制了泛型只能用于参数

下面以Action<in T>为例

public delegate void Action<in T>

public static void Main()

{

Action<Animal> actionAnimal = new Action<Animal>(a => {/*让动物叫*/ });

Action<Dog> actionDog = actionAnimal;

actionDog(aDog);

}

编译通过,因为 Action支持逆变,类型向下转换


作用:我个人肤浅的理解,之前的泛型是可以指定对某一类操作,但是无法把类的子类,父类赋值转换。有了逆变和协变,实现了泛型类的父类子类的转换。目的是为了增加语言的灵活性和能力。使泛型和委托的功能更加强大。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值