在某些情况下,我需要将对象向下转换为接口(interface)以满足我的需要,这隐含地要求向下转换通用接口(interface)的类型参数。
例子
ICage<TAnimal>
是 Cage
的接口(interface)类型的动物 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
A 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。
最佳答案
这与 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
可以突然存储任何实现 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>
, 那么设计这样的类可能更有意义:
public interface IAnimal {
IOwner Owner { get; }
}
public abstract class Mammal : IAnimal { ... }
public class Dog : Mammal { ... }
关于c# - 向下转换泛型参数时如何修复转换错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53965755/