C# 泛型的协变与逆变

那么先讲讲什么是“泛型类协变”你可以这样理解,正常的变换 好比object = String

这样的表达式一样协变主要是向上安全的变换,但是需要根据继承链条一层一层

向上变化 而不需要进行转换因为是隐式转换,先上一层继承类的代码 不过使

最容易的理解的,你认为是拆箱与装箱也没什么太大的出入 但是指泛型上的

        public class Animal // 动物
        {

        }

        public class Dog : Animal // 狗
        {

        }
上面有两个类一个为Animal一个为Dog但是Dog继承在Animal

那么下面这样的表达式毫无疑问是安全隐式转换

            Dog dog = new Dog();
            Animal animal = dog;
那么在泛型类中会是怎么样的呢?

        public interface ICovariant<out T>
        {
        }

        public class Covariant<T> : ICovariant<T>
        {
        }

        static void Main(string[] args)
        {
            ICovariant<Animal> animals = new Covariant<Dog>();
        }
本质上并有太大的出入,在正常情况下你是不可以new Convariant<Dog>

给ICovariant<Animal>的但是在C#却变得可能,而且更加高效与安全。

但是需要自己编写一个接口并且在泛型类声明T中使用out关键字,不过

System.Collections.Generic.IList<out T>也是可以进行泛型类协变的,但

是不可以进行逆变,在这里要记住一个关键字C#只允许我们给类提供一个

可以进行逆变或协变的泛型接口,意味着你继承了可以协变得接口 变不可

逆向变换,好的我们现在再来说说逆变 逆变与协变得概念相反 协变是

按照继承链条安全的向上转换,而协变则是向下变换 这就涉及到某些问题,

        public interface IContravariant<in T>
        {

        }

        public class Contravariant<T> : IContravariant<T>
        {

        }

        static void Main(string[] args)
        {
            IContravariant<Animal> Animal = new Contravariant<Animal>();
            IContravariant<Dog> dogs = Animal;
        }
看上面的代码冒失没有任何问题,编译器可以编译通过 也可以运行而不报错

但是没有人清楚的知道Animal内到底是Dog还是其他的子类型,那么你在逆变

后的Dogs中获取元素如果非Dog会返回null这就造成了一个不小安全隐患,很

多.NET程序员是依靠报错提供的信息来判断问题,然而逆变却不会出现报错信

息因为在.CLR看来它是合法的 所以使用逆变的时候需要慎重考虑

逆变的泛型委托:

        public delegate int pContravariant<in T>();

        static void Main(string[] args)
        {
            pContravariant<Animal> pAnimal = new pContravariant<Animal>(() => 250);
            pContravariant<Dog> pDogs = pAnimal;
        }
协变得泛型委托:

        public delegate int pCovariant<out T>();

        static void Main(string[] args)
        {
            pCovariant<Animal> pAnimal = new pCovariant<Dog>(() => 250);
        }
协变/逆变泛型委托概念其实与上面的泛型类的概念是差不多多少,稍微变

下便知道这里的概念,不过我估计我们写代码肯定不会有很多人会使用到

协变/逆变了不过则在我看来 的确可以使用 首先可以简化我们操作 避免涉及

大量转换造成软件不稳定,同时可以增强安全性与稳定性 何乐而不为呢?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值