在某些情况下,我需要将对象强制转换为适合我的需要的接口,这隐式要求强制转换通用接口的类型参数。
ICage<TAnimal>
是Cage
类型动物的IAnimal
的接口
public interface ICage<TAnimal>
where TAnimal : IAnimal<IOwner>
public class Cage<TAnimal> : ICage<TAnimal>
where TAnimal : IAnimal<IOwner>
public interface IAnimal<out TOwner>
where TOwner : IOwner
IAnimal
需要类型为IOwner
的所有者
public abstract class Mammal<TOwner> : IAnimal<TOwner>
where TOwner : IOwner
哺乳动物是一种动物,拥有者类型为IOwner
。
public class Human : IOwner
Human
是IOwner
的一种类型
public class Dog<TOwner> : Mammal<TOwner>
where TOwner : IOwner
狗是哺乳动物的一种。
现在将所有内容放在一起:
var cage = new Cage<Mammal<IOwner>>();
var me = new Human()
{
Name = "Hakim"
};
var dog = new Dog<Human>();
dog.Owner = me;
cage.Add((Mammal<IOwner>)dog);
在最后一行,我得到一个编译时错误CS0030,告诉我我不能将Dog转换为Mammel。
答案 0 :(得分:3)
这与you can't cast a List<string>
to a List<object>
之所以相同。
假设Mammal
中有一个名为Owner
的属性,如下所示:
public TOwner Owner { get; set; }
对于Mammal<IOwner>
的实例,它变为:
public IOwner Owner { get; set; }
dog
是Dog<Human>
,也是Mammal<Human>
。 如果您可以将dog
强制转换为Mammal<IOwner>
,这意味着dog.Owner
可以突然存储实现{{1}的任何类型}。即有可能:
IOwner
但这是不可能的,因为运行时的class EvilOwner : IOwner { ... }
Mammal<IOwner> mammal = (Mammal<IOwner>)dog;
mammal.Owner = new EvilOwner();
是dog
,其Dog<Human>
为Owner
。 Human
可能无法存储在EvilOwner
中!
我建议您做的是删除Human
通用参数。如果您认为TOwner
也是 Dog<Human>
的一种,那么设计这样的类可能更有意义:
Mammal<IOwner>