泛型与类继承的混淆

尼克·阿尔布雷希特

我有以下代码块作为我遇到的问题的简化示例。但是我收到一个错误消息,声称我无法将一种类型转换为另一种类型。我使用LINQPad进行了测试。

void Main()
{
    LivingThing<Appendage> mysteryAnimal = new Cat();
}

public class Appendage { }
public class Paw : Appendage { }

public class LivingThing<TExtremity> where TExtremity : Appendage { }
public class Animal<TExtremity> : LivingThing<TExtremity> where TExtremity : Appendage { }
public class Cat : Animal<Paw> { }

为什么我不能投CatLivingThing<Appendage>,当我知道猫的定义是使用的子类LivingThingAppendage

谢尔盖·卡里尼琴科(Sergey Kalinichenko)

通过向其中一个类中添加一种方法,不难理解为什么您尝试执行的操作无法进行一些修改:

public class LivingThing<TExtremity> where TExtremity : Appendage {
    private TExtremity extremity;
    public void SetExtremity(TExtremity e) {
        extremity = e;
    }
}

现在,让我们想象一下C#可以让您完成分配。然后,它应该让您执行此操作:

public class Hand : Appendage { }
...
// Let's pretend this works
LivingThing<Appendage> cat = new Cat();
// Now that C# let us do the assignment above, it must allow this too,
// because Cat is a LivingThing and Hand is an Appendage:
cat.SetExtremity(new Hand());

糟糕,我们有一只手扶着的猫!C#不应该让我们这样做。

但是,如果LivingThing返回的 方法,则可以做您想做的事情TExtremityC#提供了定义继承层次结构的方法,使您可以按照自己的尝试灵活地分配。这是修改后的代码,可以正常工作:

void Main()
{
    ILivingThing<Appendage> mysteryAnimal = new Cat();
}

public class Appendage { }
public class Paw : Appendage { }

public interface ILivingThing<out TExtremity> where TExtremity : Appendage { }
// You have a choice of keeping Animal a class. If you do, the assignment
// Animal<Appendage> mysteryAnimal = new Cat()
// would be prohibited.
public interface IAnimal<TExtremity> : ILivingThing<out TExtremity> where TExtremity : Appendage { }
public class Cat : Animal<Paw> { }

有一个陷阱:既不允许ILivingThing<TExtremity>也不IAnimal<TExtremity>具有类型TExtremity或方法TExtremity作为参数的可设置属性

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

Related 相关文章

热门标签

归档