Ste*_*bbi 7 .net generics casting implicit-conversion
我的目标是.NET 3.5.假设我有一个类Bob,它是SubBob的抽象基类.
我可以声明这个:
Bob b = new SubBob();
但我不能这样做:
 // compliation error - can't convert
BindingList<Bob> myList = new BindingList<SubBob>(); 
我的猜测是BindingList不希望你这样做,因为它必须知道右侧的类型与左侧的内存布局相同.SubBob的大小可能比Bob大.
有没有办法可以进行隐式转换,还是需要强制转换?
通过实例BindingList<SubBob>你限制它的工作SubBob和更具体的类型(例如SubSubBob).
如果您想要Bob适合那里,请声明myList为您要支持的最不具体类型的列表:
BindingList<Bob> myList = new BindingList<Bob>(); 
(或者,更方便)
var myList = new BindingList<Bob>(); 
它不是关于内存(BindingList只包含对象的引用,并且所有引用都具有相同的大小),而是关于您将引入的逻辑不一致.
如果可以使用此类代码,您可以随意破坏类型限制:
BindingList<Animal> myList = new BindingList<Cat>(); 
myList.Add(new Dog()); // bang!
myList是一个Cats 的列表,你期望它如何处理Dog?  
编译器不会知道存在问题,并且很乐意编译您的代码.这段代码运行时会发生什么?例外?但是引入了仿制药来解决类型安全问题.
在.NET 4.0中,为代理和接口(不是类)添加了通用协方差和逆变.例如,是协变,这意味着可以将其分配给任何类型的可变少衍生比:IEnumerable<out T>T
IEnumerable<Cat> cats = new List<Cat> { new Cat("Hudson"), new Cat("Crookshanks") };
IEnumerable<Animal> animals = cats; // sequence of cats is sequence of animals
但这只是可能的,因为IEnumerable<out T>保证它只返回 T(关键字out)并且永远不接受它.如果它被接受T作为参数,它将打开上述问题的大门.出于这个原因,ICollection是不是协变.
以类似的方式,一些接口保证它们只接受 T(关键字in)并且永远不会返回它.这样的接口称为逆变,允许更具体地 赋值给变量T:
IComparer<Animal> animalComparer = // ...
IComparer<Dog> dogComparer = animalComparer; // comparer of animals is comparer of dogs
| 归档时间: | 
 | 
| 查看次数: | 947 次 | 
| 最近记录: |