泛型类型的奇怪行为
本文关键字:泛型类型 | 更新日期: 2023-09-27 17:56:15
请看下面的简单代码
public class A{}
public class B: A{}
public class G<T> where T : A
{
public T GetT()
{
return new A();
}
}
此代码不正确 - 编译器错误"无法将 A 转换为返回类型 T"。但A实际上是T。如果我改变
return new A();
自
return new A() as T;
一切都很好。这种行为的原因是什么?提前致谢
UPD:最初的问题有误。现已修复
想象一下,如果你这样做会发生什么:
public class C : A{}
G<C> x = new G();
C c = x.GetT();
你真的不希望它返回一个B
引用......
as
运算符工作是因为如果T
既不B
也不A
,它只会返回null
......但这可能不是你真正的意思。
很难知道要建议的行动方案,而不知道你想做什么。
根据更新重新设计的答案
虽然A
满足泛型约束where T : A
,但它是一个具体的类型。但是,泛型类的 GetT()
方法具有泛型返回类型 T
,因此您必须将具体类型强制转换为泛型类型以使返回兼容。
旧答案适用于您之前返回new B()
的情况。
旧答案
泛型类型约束说T
必须继承自A
;然而,它并没有说T
必须B
(或它的派生),尽管B
碰巧自己继承自A
并满足约束。
所以返回类型不兼容(B
总是B
,但T
不一定是B
),你得到错误。
相同的代码,只是名称已更改
public class Animal{}
public class G<T> where T : Animal
{
public T GetT()
{
return new Animal();
}
}
Fish fish = new G<Fish>().GetT();
但是 GetT() 不返回 Fish,它返回一个匿名的"Animal"。有一个问题:即使相反,所有的动物都不是鱼。如果需要鱼,则不能归还动物,而不需要任何其他种类的动物。
where T : A
表示T必须从A继承。 因此,T
可能不是A
,所以你不能只返回一个B
,因为C
也可能是从A
继承的,但B
不是C
。