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



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。

最佳答案

这与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可以突然存储实现IOwner的任何类型。即这是可能的:

class EvilOwner : IOwner { ... }

Mammal<IOwner> mammal = (Mammal<IOwner>)dog;
mammal.Owner = new EvilOwner();


但这是不可能的,因为在运行时dogDog<Human>,其OwnerHumanEvilOwner可能无法存储在Human中!

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

public interface IAnimal {
    IOwner Owner { get; }
}

public abstract class Mammal : IAnimal { ... }

public class Dog : Mammal { ... }

关于c# - 强制转换通用参数时如何解决强制转换错误,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53965755/

10-15 22:44