我的目标是.NET 3.5。假设我有一个类Bob,它是SubBob的抽象基类。
我可以声明:
Bob b = new SubBob();但我不能这么做:
// compliation error - can't convert
BindingList<Bob> myList = new BindingList<SubBob>(); 我的猜测是BindingList不希望您这样做,因为它必须知道位于右侧的类型与位于左侧的类型具有相同的内存布局。SubBob的尺寸可能比鲍勃的大。
有没有一种方法可以进行隐式转换,或者需要强制转换?
发布于 2011-08-01 20:53:48
简短的回答
通过实例化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是一个Cat列表,你希望它如何处理一个Dog?
编译器不会知道有问题,它会很高兴地编译你的代码。当这段代码运行时会发生什么?一个例外?但泛型正是为了解决类型安全问题而引入的。
关于协方差和逆方差的一个附注
在.NET 4.0中,为委托和接口添加了generic covariance and contravariance是正确的(不是为类添加的)。例如,IEnumerable是协变的,这意味着您可以将它赋给派生比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 (T),并且永远不会返回 it。这样的接口被称为逆变量,并允许赋值给具有更具体T的变量
IComparer<Animal> animalComparer = // ...
IComparer<Dog> dogComparer = animalComparer; // comparer of animals is comparer of dogs发布于 2011-08-01 20:47:49
与您的案例相关的,特别是
您在这里处理的是contravariance,而一个类只能支持协方差或逆方差。IEnumerable<T>支持协方差。
它的签名是IEnumerable<out T>,所以它支持T中类的继承类。
通用中的
不幸的是,这在.NET 3.5中不可用。
它是在.NET 4中作为Covariance and Contravariance引入的。
这就是a FAQ on the subject at MSDN。以下是摘录:
// Assignment compatibility.
string str = "test";
// An object of a more derived type is assigned to an object of a less derived type.
object obj = str;
// Covariance.
IEnumerable<string> strings = new List<string>();
// Contravariance.
// Assume that I have this method:
// static void SetObject(object o) { }
Action<object> actObject = SetObject;发布于 2011-08-01 20:53:40
有没有隐式转换的方法,或者是否需要强制转换?
下面应该允许继承Bob的任何类作为Bob添加到列表中。
BindingList<Bob> myList = new BindingList<Bob>(); 你到底想做什么?
https://stackoverflow.com/questions/6898583
复制相似问题