强制转换通用参数时如何解决强制转换错误

时间:2018-12-29 00:40:01

标签: c# generics inheritance interface

在某些情况下,我需要将对象强制转换为适合我的需要的接口,这隐式要求强制转换通用接口的类型参数。

示例

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

HumanIOwner的一种类型

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。

1 个答案:

答案 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; }

dogDog<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>OwnerHuman可能无法存储在EvilOwner中!

我建议您做的是删除Human通用参数。如果您认为TOwner 也是 Dog<Human>的一种,那么设计这样的类可能更有意义:

Mammal<IOwner>