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

本文关键字:受约束 泛型 转换 不能 对象 为什么 | 更新日期: 2023-09-27 18:16:57

假设我有以下接口和实现它的类:

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

为什么不可能从我的具体类强制转换为一般约束为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
    }
}

如果我将animal的字段类型改为IAnimal而不是animal,那么它会编译ok:

public class Zoo
{
    private readonly IAnimal animal = new Animal();
    public TAnimal GetAnimal<TAnimal>() where TAnimal : IAnimal
    {
        return (TAnimal)(this.animal); // this compiles
    }
}

或者,如果我在转换为泛型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
    }
}

所以我的问题是-为什么第一个版本不能工作?编译器肯定有足够的信息知道Animal实现了IAnimal,所以给定约束,将其强制转换为TAnimal是有效的吗?还是我遗漏了什么?

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

Animal继承IAnimal, TAnimal不继承Animal,但也继承IAnimal。如果B不继承A,则不能从A强制转换为B,它将类似于:

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

即使DataTablestring继承自object,也不能这样做。要在没有继承关系的类型之间进行转换,必须定义转换操作符

假设您还有一个类Dog:

public class Dog : IAnimal 
{
} 

如果你用Dog作为TAnimal调用你的方法:GetAnimal<TAnimal>(),你会得到这样的代码:

public class Zoo
{
    private readonly Animal animal = new Animal();
    public Dog GetAnimal()
    {
        return (Dog)this.animal;
    }
}

当然,Dog不继承Animal,所以cast是错误的。

然后是第二个例子:

public class Zoo
{
    private readonly IAnimal animal = new Animal();
    public Dog GetAnimal()
    {
        return (Dog)this.animal;
    }
}

Dog正在实现IAnimal,所以这将被编译。然而,它会在运行时抛出一个InvalidCastException。同样的事情也适用于第三个示例中的双强制转换:

public class Zoo
{
    private readonly Animal animal = new Animal();
    public Dog GetAnimal()
    {
        return (Dog)(IAnimal)this.animal;
    }
}

你可以从Animal强制转换到IAnimal,从IAnimal强制转换到Dog,但是它会抛出InvalidCastException