van*_*161 5 c# generics casting
我在转换泛型类型时遇到问题.
例如我有课程:
public class Dog
{
}
public class Husky : Dog
{
}
public class MyWrapper<T> where T : class
{
}
Run Code Online (Sandbox Code Playgroud)
然后我想做这样的事情,但我不知道怎么做
MyWrapper<Husky> husky = new MyWrapper<Husky>();
List<MyWrapper<Dog>> dogs= new List<MyWrapper<Dog>>();
dogs.Add(husky); // how to cast husky to MyWrapper<Dog>?
Run Code Online (Sandbox Code Playgroud)
编辑:更改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
{
}
Run Code Online (Sandbox Code Playgroud)
然后你可以这样做:
var husky = new MyWrapper<Husky>();
var dogs = new List<IMyWrapper<Dog>>();
dogs.Add(husky);
Run Code Online (Sandbox Code Playgroud)
我担心你不能 - 虽然Husky是Dog,但Animal<Husky>不是Animal<Dog>.
有关类似问题,请参阅.NET Casting Generic List.
您为什么不安排类继承的原因如下?我不确定为什么Animal需要接受一个类型参数.
public abstract class Animal
{
}
public class Dog : Animal
{
}
public class Husky : Dog
{
}
Run Code Online (Sandbox Code Playgroud)
你需要协方差-向上转换一个泛型类型- 。
但 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
{
}
Run Code Online (Sandbox Code Playgroud)
现在这将起作用:
List<IAnimal<Dog>> list = new List<IAnimal<Dog>>();
list.Add(new Animal<Husky>());
Run Code Online (Sandbox Code Playgroud)
在 MSDN 上了解有关协方差和逆变的更多信息:
无论如何......通用约束的重点是T : class什么?你只知道那T是一个类,但它可能没有公共构造函数,或者它可能是一块石头而不是一条狗,谁知道呢?
或者,这个类层次结构的重点是什么?正如其他人在他们的回答中指出的那样,你的层次结构不是非常面向对象的:a Dog IS an animal so Dog DERIVES Animal。
只是改变它,你就不再需要使用泛型类型参数了。
也许你更喜欢组合而不是继承,但我倾向于决定什么是最好的这个问题:
如果我说专业类型,我可以说“B 是 A”吗?=>然后我选择继承。
如果我谈论专业类型,我可以说“B 是 A 的一部分”=>然后我选择组合。
实际上,我相信协方差可以解决您的问题,但我觉得这是该语言功能的错误用例。