简体   繁体   English

为什么我不能将对象强制转换为约束泛型?

[英]Why can't I cast an object to a constrained generic?

Given that I have the following interface and a class that implements it: 鉴于我有以下接口和一个实现它的类:

public interface IAnimal
{
    void Feed();
}

public class Animal : IAnimal
{
    public void Feed()
    {
        // feed
    }
}

Why is it not possible to cast from my concrete class to a generic constrained to be IAnimal, when my Animal class implements it? 当我的Animal类实现它时,为什么不能从我的具体类转换为通用约束为IAnimal?

public class Zoo
{
    private readonly Animal animal = new Animal();

    public TAnimal GetAnimal<TAnimal>() where TAnimal : IAnimal
    {
        return (TAnimal)(this.animal); // This will not compile
    }
}

If I change the field type of animal to be IAnimal rather than Animal then it compiles ok: 如果我将动物的野外类型更改为IAnimal而不是Animal,那么它编译好了:

public class Zoo
{
    private readonly IAnimal animal = new Animal();

    public TAnimal GetAnimal<TAnimal>() where TAnimal : IAnimal
    {
        return (TAnimal)(this.animal); // this compiles
    }
}

Or alternatively if I do an explicit cast to IAnimal before the cast to the generic TAnimal then this will also compile fine: 或者,如果我在强制转换为通用TAnimal之前对IAnimal进行显式转换,那么这也可以正常编译:

public class Zoo
{
    private readonly Animal animal = new Animal();

    public TAnimal GetAnimal<TAnimal>() where TAnimal : IAnimal
    {
        return (TAnimal)((IAnimal)this.animal); // this compiles
    }
}

So my question is - why doesn't the first version work? 所以我的问题是 - 为什么第一个版本不起作用? Surely the compiler has enough information to know that Animal implements IAnimal, so given the constraint it would be valid to cast it to TAnimal? 当然编译器有足够的信息来知道Animal实现了IAnimal,所以给定约束将它转换为TAnimal是有效的吗? Or is there something I am missing here? 或者我在这里缺少什么?

Animal inherits from IAnimal and TAnimal doesn't inherit from Animal , but from IAnimal too. Animal继承自IAnimalTAnimal不继承自Animal ,也来自IAnimal You can't cast from A to B if B doesn't inherit from A , it would be something like: 如果B不从A继承,则不能从AB ,它将类似于:

DataTable dt = new DataTable();
string str = (string)dt;

You can't do this even though DataTable and string inherit from object . 即使DataTablestringobject继承,也不能这样做。 To convert between types that aren't related by inheritance you have to define conversion operators 要通过继承转换不相关的类型,您必须定义转换运算符

Suppose you have also a class Dog : 假设你还有一个类Dog

public class Dog : IAnimal 
{

} 

If you invoke your method: GetAnimal<TAnimal>() with Dog as TAnimal you will have a code like this: 如果你使用Dog作为TAnimal调用你的方法: GetAnimal<TAnimal>() ,你将得到如下代码:

public class Zoo
{
    private readonly Animal animal = new Animal();

    public Dog GetAnimal()
    {
        return (Dog)this.animal;
    }
}

Of course Dog does not inherit from Animal so the casting is wrong. 当然Dog不会继承Animal所以施法是错误的。

Then you have your second example: 然后你有第二个例子:

public class Zoo
{
    private readonly IAnimal animal = new Animal();

    public Dog GetAnimal()
    {
        return (Dog)this.animal;
    }
}

Dog is implementing IAnimal , so this will compile. Dog正在实现IAnimal ,所以这将编译。 It will however throw a InvalidCastException in runtime. 但是它会在运行时抛出InvalidCastException The same thing applies to the double casting in your third example: 同样的事情适用于第三个例子中的双重投射:

public class Zoo
{
    private readonly Animal animal = new Animal();

    public Dog GetAnimal()
    {
        return (Dog)(IAnimal)this.animal;
    }
}

You can cast from Animal to IAnimal and from IAnimal to Dog , however it will throw InvalidCastException . 你可以从AnimalIAnimal ,从IAnimalDog ,但它会抛出InvalidCastException

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM