c# - 向下转换泛型参数时如何修复转换错误

标签 c# generics inheritance interface

在某些情况下,我需要将对象向下转换为接口(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 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> . 如果可以施放dogMammal<IOwner> ,这意味着 dog.Owner可以突然存储任何实现 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> , 那么设计这样的类可能更有意义:

public interface IAnimal {
    IOwner Owner { get; }
}

public abstract class Mammal : IAnimal { ... }

public class Dog : Mammal { ... }

关于c# - 向下转换泛型参数时如何修复转换错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53965755/

相关文章:

inheritance - swift 子类*总是*必须调用 super.init()

c# - 正则表达式将字符串中的日期与 where 子句匹配

c# - 如何在 DataGridView 中为列设置密码

swift - 为类创建通用委托(delegate)

Java模板方法模式

c# - 计算每个派生类的类实例

C# 3.0 目标 2.0

c# - 从 BitmapImage 获取支持的图像格式

c# - 这种使用泛型的模式有名称吗?

java - 删除代码重复