简体   繁体   English

在C#中转换泛型类

[英]Casting generic classes in C#

I have a problem with casting generic types. 我在转换泛型类型时遇到问题。

For example I have classes: 例如我有课程:

public class Dog
{
}

public class Husky : Dog
{

}

public class MyWrapper<T> where T : class
{
}

and then I want to do something like this, but I don't know how 然后我想做这样的事情,但我不知道怎么做

MyWrapper<Husky> husky = new MyWrapper<Husky>();
List<MyWrapper<Dog>> dogs= new List<MyWrapper<Dog>>();
dogs.Add(husky); // how to cast husky to MyWrapper<Dog>?

EDIT: Changed Animal<T> to MyWrapper<T> , so it will be more adequate example 编辑:将Animal<T>更改为MyWrapper<T> ,因此它将是更充分的示例

You could use the generic covariance of interfaces in C# 4 or later. 您可以在C#4或更高版本中使用接口的通用协方差 In order to do so, you'd need to define a covariant interface (using out ) and have MyWrapper implement that interface: 为此,您需要定义一个协变接口(使用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
{
}

Then you can do this: 然后你可以这样做:

var husky = new MyWrapper<Husky>();
var dogs = new List<IMyWrapper<Dog>>();
dogs.Add(husky);

I'm afraid you can't - although Husky is a Dog , Animal<Husky> is not an Animal<Dog> . 我担心你不能 - 虽然HuskyDogAnimal<Husky>不是Animal<Dog>

See .NET Casting Generic List for a similar question. 有关类似问题,请参阅.NET Casting Generic List

Any reason why you would not arrange your class inheritance as follows? 您为什么不安排类继承的原因如下? I am not sure why Animal needs to accept a type parameter. 我不确定为什么Animal需要接受一个类型参数。

public abstract class Animal
{
}

public class Dog : Animal
{
}

public class Husky : Dog 
{
}

You need covariance for that - upcasting a generic type -. 你需要协方差 - 向上转换泛型类型 - 。

But C# covariance is only supported on: 但只支持C#协方差:

  • Delegates. 代表们。
  • Interfaces. 接口。

For that reason, I only find a solution: create a marker interface IAnimal<T> : 出于这个原因,我只找到一个解决方案: 创建一个标记接口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
{
}

And now this will work: 现在这将有效:

        List<IAnimal<Dog>> list = new List<IAnimal<Dog>>();
        list.Add(new Animal<Husky>());

Learn more about covariance and contravariance on MSDN: 了解有关MSDN上协方差和逆变的更多信息:

UPDATE UPDATE

Anyway... what's the point of the generic constraint T : class ? 无论如何......通用约束T : class什么? You only know that T is a class, but it could have no public constructor, or it could be a rock instead of a dog, who knows? 你只知道T是一个类,但它可能没有公共构造函数,或者它可能是摇滚而不是狗,谁知道?

Or, what's the point of this class hierarchy? 或者,这个类层次结构的重点是什么? As other have pointed out in their answers, your hierarchy isn't very object-oriented-ish: a Dog IS an animal so Dog DERIVES Animal . 正如其他人在他们的答案中所指出的那样,你的等级制度并不是非常面向对象的 - ish:狗是一种动物,所以Dog DERIVES Animal

Just changing that, you've lost the need of using generic type parameters. 只是改变它,你就失去了使用泛型类型参数的需要。

Maybe you prefer composition over inheritance, but I tend to decide what's best with this question: 也许你更喜欢构图而不是继承,但我倾向于决定这个问题最好的是什么:

  • If I talk about the specialized type, can I say "B is A"? 如果我谈论专业类型,我可以说“B是A”吗? => Then I choose inheritance . => 然后我选择继承

  • If I talk about the specialized type, can I say "B is part of A" => Then I choose composition . 如果我谈论专业类型,我可以说“B是A的一部分”=> 然后我选择组合

Actually I believe that covariance solves your question, but I feel it's a wrong use case of this language feature. 实际上我相信协方差可以解决你的问题,但我觉得这个语言功能的用例是错误的。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM