码迷,mamicode.com
首页 > Windows程序 > 详细

C# 泛型的协变与逆变

时间:2015-06-16 09:25:34      阅读:459      评论:0      收藏:0      [点我收藏+]

标签:泛型   逆变   协变   c#   

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

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

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

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

[csharp] view plaincopy
  1. public class Animal // 动物  
  2. {  
  3.   
  4. }  
  5.   
  6. public class Dog : Animal // 狗  
  7. {  
  8.   
  9. }  
上面有两个类一个为Animal一个为Dog但是Dog继承在Animal

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

[csharp] view plaincopy
  1. Dog dog = new Dog();  
  2. Animal animal = dog;  
那么在泛型类中会是怎么样的呢?

[csharp] view plaincopy
  1. public interface ICovariant<out T>  
  2. {  
  3. }  
  4.   
  5. public class Covariant<T> : ICovariant<T>  
  6. {  
  7. }  
  8.   
  9. static void Main(string[] args)  
  10. {  
  11.     ICovariant<Animal> animals = new Covariant<Dog>();  
  12. }  
本质上并有太大的出入,在正常情况下你是不可以new Convariant<Dog>

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

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

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

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

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

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

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

[csharp] view plaincopy
  1. public interface IContravariant<in T>  
  2. {  
  3.   
  4. }  
  5.   
  6. public class Contravariant<T> : IContravariant<T>  
  7. {  
  8.   
  9. }  
  10.   
  11. static void Main(string[] args)  
  12. {  
  13.     IContravariant<Animal> Animal = new Contravariant<Animal>();  
  14.     IContravariant<Dog> dogs = Animal;  
  15. }  
看上面的代码冒失没有任何问题,编译器可以编译通过 也可以运行而不报错

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

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

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

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

逆变的泛型委托:

[csharp] view plaincopy
  1. public delegate int pContravariant<in T>();  
  2.   
  3. static void Main(string[] args)  
  4. {  
  5.     pContravariant<Animal> pAnimal = new pContravariant<Animal>(() => 250);  
  6.     pContravariant<Dog> pDogs = pAnimal;  
  7. }  
协变得泛型委托:

[csharp] view plaincopy
  1. public delegate int pCovariant<out T>();  
  2.   
  3. static void Main(string[] args)  
  4. {  
  5.     pCovariant<Animal> pAnimal = new pCovariant<Dog>(() => 250);  
  6. }  
协变/逆变泛型委托概念其实与上面的泛型类的概念是差不多多少,稍微变

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

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

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

C# 泛型的协变与逆变

标签:泛型   逆变   协变   c#   

原文地址:http://blog.csdn.net/u012395622/article/details/46508931

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!