[英]Casting generic classes in C#
我在转换泛型类型时遇到问题。
例如我有课程:
public class Dog
{
}
public class Husky : Dog
{
}
public class MyWrapper<T> where T : class
{
}
然后我想做这样的事情,但我不知道怎么做
MyWrapper<Husky> husky = new MyWrapper<Husky>();
List<MyWrapper<Dog>> dogs= new List<MyWrapper<Dog>>();
dogs.Add(husky); // how to cast husky to MyWrapper<Dog>?
编辑:将Animal<T>
更改为MyWrapper<T>
,因此它将是更充分的示例
您可以在C#4或更高版本中使用接口的通用协方差 。 为此,您需要定义一个协变接口(使用out
)并让MyWrapper
实现该接口:
public class Dog
{
}
public class Husky : Dog
{
}
public class MyWrapper<T> : IMyWrapper<T> where T : class
{
}
public interface IMyWrapper<out T> where T : class
{
}
然后你可以这样做:
var husky = new MyWrapper<Husky>();
var dogs = new List<IMyWrapper<Dog>>();
dogs.Add(husky);
我担心你不能 - 虽然Husky
是Dog
, Animal<Husky>
不是Animal<Dog>
。
有关类似问题,请参阅.NET Casting Generic List 。
您为什么不安排类继承的原因如下? 我不确定为什么Animal需要接受一个类型参数。
public abstract class Animal
{
}
public class Dog : Animal
{
}
public class Husky : Dog
{
}
你需要协方差 - 向上转换泛型类型 - 。
但只支持C#协方差:
出于这个原因,我只找到一个解决方案: 创建一个标记接口IAnimal<T>
:
public class Dog
{
}
public class Husky : Dog
{
}
public interface IAnimal<out T>
where T : class
{
}
public class Animal<T> : IAnimal<T> where T : class
{
}
现在这将有效:
List<IAnimal<Dog>> list = new List<IAnimal<Dog>>();
list.Add(new Animal<Husky>());
了解有关MSDN上协方差和逆变的更多信息:
无论如何......通用约束T : class
什么? 你只知道T
是一个类,但它可能没有公共构造函数,或者它可能是摇滚而不是狗,谁知道?
或者,这个类层次结构的重点是什么? 正如其他人在他们的答案中所指出的那样,你的等级制度并不是非常面向对象的 - ish:狗是一种动物,所以Dog
DERIVES Animal
。
只是改变它,你就失去了使用泛型类型参数的需要。
也许你更喜欢构图而不是继承,但我倾向于决定这个问题最好的是什么:
如果我谈论专业类型,我可以说“B是A”吗? => 然后我选择继承 。
如果我谈论专业类型,我可以说“B是A的一部分”=> 然后我选择组合 。
实际上我相信协方差可以解决你的问题,但我觉得这个语言功能的用例是错误的。
不可能Animal<Husky>
不是来自Animal<Dog>
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.