c# - C#泛型类继承混淆
问题描述
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。
我不能有一个从基类派生的泛型类型并且仍然使用它吗?
解决方案
问题是,如果您想要的是合法的,那么这也是合法的:
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
现在我们在水族馆里养了一只长颈鹿,没有人高兴。
此功能称为协变,它仅适用于泛型接口和委托,当它们使用引用类型构造时,它们专门设计用于处理方差并由编译器检查安全性。
例如,您可以在预期 anIEnumerable<Fish>
的上下文中使用 an,IEnumerable<Animal>
因为无法将长颈鹿添加到动物序列中。
我不能有一个从基类派生的泛型类型并且仍然使用它吗?
是的,但你必须遵守规则。这些规则是为了保证你的安全。了解类型系统如何工作并使用它来帮助防止您的错误,您将永远不会错误地将长颈鹿放入水族箱。
推荐阅读
- javascript - 正则表达式 - 捕获标记的模板文字
- c++ - 菜单驱动程序搜索功能
- javascript - 防止反应按钮组件中的默认按钮行为(页面重新加载)
- azure-data-factory - 使用 rest api 创建在数据工厂 v2 中运行的管道
- textures - Assimp 不从层文件中读取纹理坐标信息
- c++ - 如何调整静态控件以显示阿拉伯语(从右到左)文本?
- java - 在 Java + Spring + JPA 中模拟死锁?
- pandas-apply - 应用返回数据框
- python - 如何对具有非唯一值的倒排字典进行排序?
- sockets - 几次迭代后,在匿名线程内使用 wi-fi 套接字传输数据停止 - 已关闭