在C#中转换泛型类

时间:2013-01-23 08:58:29

标签: c# generics casting

我在转换泛型类型时遇到问题。

例如我有课程:

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>,因此会更加充实

5 个答案:

答案 0 :(得分:8)

您可以使用C#4或更高版本中的generic covariance接口。为此,您需要定义一个协变接口(使用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);

答案 1 :(得分:7)

我担心你不能 - 虽然HuskyDogAnimal<Husky>不是Animal<Dog>

有关类似问题,请参阅.NET Casting Generic List

答案 2 :(得分:6)

您不会按如下方式安排类继承的原因?我不确定为什么Animal需要接受类型参数。

public abstract class Animal
{
}

public class Dog : Animal
{
}

public class Husky : Dog 
{
}

答案 3 :(得分:4)

您需要协方差 - 向上转换泛型 - 。

但只支持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是一个类,但它可能没有公共构造函数,或者它可能是摇滚而不是狗,谁知道?

或者,这个类层次结构有什么意义?正如其他人在他们的答案中指出的那样,你的层次结构不是非常面向对象的 - 是一只狗是一种动物所以Dog DERIVES {{1 }}

只需更改它,您就不再需要使用泛型类型参数。

也许你更喜欢构图而不是继承,但我倾向于用这个问题来决定什么是最好的:

  • 如果我谈论专业类型,我可以说“B是A”吗? =&GT; 然后我选择继承

  • 如果我谈论专业类型,我可以说“B是A的一部分”=&gt; 然后我选择合成

实际上我相信协方差可以解决您的问题,但我觉得这个语言功能的用例是错误的。

答案 4 :(得分:2)

不可能Animal<Husky>不是来自Animal<Dog>