鉴于我有以下接口和一个实现它的类:
public interface IAnimal
{
void Feed();
}
public class Animal : IAnimal
{
public void Feed()
{
// feed
}
}
当我的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
}
}
如果我将动物的野外类型更改为IAnimal而不是Animal,那么它编译好了:
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是有效的吗?或者我在这里缺少什么?
答案 0 :(得分:4)
Animal
继承自IAnimal
而TAnimal
不会继承自Animal
,也来自IAnimal
。如果A
未从B
继承,则无法从B
投射到A
,它将类似于:
DataTable dt = new DataTable();
string str = (string)dt;
即使DataTable
和string
继承自object
,也无法执行此操作。要在继承无关的类型之间进行转换,您必须定义conversion operators
答案 1 :(得分:1)
假设您还有一个班级Dog
:
public class Dog : IAnimal
{
}
如果您调用方法:GetAnimal<TAnimal>()
Dog
为TAnimal
,您将获得如下代码:
public class Zoo
{
private readonly Animal animal = new Animal();
public Dog GetAnimal()
{
return (Dog)this.animal;
}
}
当然Dog
不会从Animal
继承,因此投射错误。
然后你有了第二个例子:
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
。