在 C# 中强制转换泛型类

本文关键字:转换 泛型类 | 更新日期: 2023-09-27 17:55:12

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

例如,我有课程:

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# 中强制转换泛型类

可以在 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是一个DogAnimal<Husky>不是Animal<Dog>

有关类似问题,请参阅 .NET 强制转换泛型列表。

您不按以下方式安排类继承的任何原因?我不确定为什么动物需要接受类型参数。

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 上的协方差和逆变的详细信息:

  • http://msdn.microsoft.com/en-us/library/dd799517.aspx

更新

无论如何。。。泛型约束T : class的意义何在?你只知道T是一个类,但它可能没有公共构造函数,或者它可以是一块石头而不是一只狗,谁知道呢?

或者,这个类层次结构的意义何在?正如其他人在他们的答案中指出的那样,你的层次结构不是非常面向对象:狗是一种动物,所以Dog派生Animal

只是改变这一点,你就不再需要使用泛型类型参数了。

也许你更喜欢组合而不是继承,但我倾向于决定这个问题的最佳选择:

  • 如果我谈论专业类型,我可以说"B 是 A"吗?=> 然后我选择继承

  • 如果我谈论专业类型,我可以说"B 是 A 的一部分"=> 然后我选择构图

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

不可能Animal<Husky>不是从Animal<Dog>派生的。