标签:泛型 逆变 协变 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);
-
}
协变/逆变泛型委托概念其实与上面的泛型类的概念是差不多多少,稍微变通
下便知道这里的概念,不过我估计我们写代码肯定不会有很多人会使用到
协变/逆变了不过则在我看来 的确可以使用 首先可以简化我们操作 避免涉及
大量转换造成软件不稳定,同时可以增强安全性与稳定性 何乐而不为呢?
C# 泛型的协变与逆变
标签:泛型 逆变 协变 c#
原文地址:http://blog.csdn.net/u012395622/article/details/46508931