abstract class BaseClassA{}
class DerivedClassA : BaseClassA{}
abstract class BaseClassB<T> where T : BaseClassA
{
public T foo;
}
class DerivedClassB : BaseClassB<DerivedClassA>
{
public DerivedClassB(DerivedClassA _foo)
{
foo = _foo;
}
}
class Test
{
DerivedClassB foobar = new DerivedClassB();
void main()
{
//Error: casting not possible
BaseClassA<BaseClassB> bar = new DerivedClassA<DerivedClassB>(foobar);
}
}
嘿大家好
我有一点问题。上面的代码给了我一个“无法投射”的例外。
我希望能够访问DerivedClassB的foo,而无需将其从BaseClassA转换为DerivedClassA。
我不能从基类派生泛型类型并仍然使用它吗?
答案 0 :(得分:2)
问题在于,如果您想要的是合法的,那么这也是合法的:
abstract class Animal {}
class Goldfish : Animal {}
class Giraffe : Animal {}
abstract class Cage<T> where T : Animal {
void Add(T newAnimal) { ... }
}
class Aquarium : Cage<Goldfish> { }
...
Cage<Animal> c = new Aquarium(); // This is not legal, but suppose it was
c.Add(new Giraffe()); // A giraffe is an animal
现在我们在水族馆里养了一头长颈鹿,没有人喜欢。
此功能称为协方差,它仅适用于通用接口和委托,当它们使用引用类型构建时,它们是专门设计用于处理差异并由编译器检查安全性。
例如,您可以在期望IEnumerable<Fish>
的上下文中使用IEnumerable<Animal>
,因为无法将长颈鹿添加到动物序列中。
我是否有从基类派生的泛型类型并仍在使用它?
是的,但你必须遵守规则。 这些规则可以保证您的安全。了解类型系统如何工作并使用它来帮助防止你的错误,你永远不会错误地将长颈鹿放入水族馆。