c# - 为什么派生类的泛型会产生非派生类?

标签 c# oop generics polymorphism

假设我们有两个类 AB其中 B 派生自 A。

class A
{
}

class B : A
{
}

class C<T>
{
}

现在C<B> 不派生C<A> .

这让我有点困惑,因为我坚信我可以用 A 做的“一切”,我也可以用 B 做。 我确信我遗漏了一些东西,因为它似乎与 OOP 的基础知识相矛盾。

有什么具体的理由和例子吗?

编辑:

我读过很多类似的帖子,例如: In C#, why can't a List<string> object be stored in a List<object> variable

Why can't I cast a dictionary of one value type to dictionary of another value type when the value types can be cast from one another?

Casting from IEnumerable<Object> to IEnumerable<string>

但在每篇文章中,答案都集中在一个特定的类/数据结构上,并使这个特定的代码起作用,而不是为什么它在一般情况下是不可能的?

最佳答案

I though that "everything" I can do with A, I can do with B. I'm sure that I'm missing something because it seems contradicting to the basics of OOP.

让我们首先说明 basic principle你在暗示。来自维基百科:

If S is a subtype of T, then objects of type T may be replaced with objects of type S without altering any of the desirable properties of that program

您缺少的是关键字:对象

您可以替换类型为 B对象任何类型为 A对象是必须的。但事实并非如此,你可以用类型做所有事情 A您还可以使用类型 B .如果有人向您要车,而您给了他们一辆 1995 年的福特 Escort,他们可以将其用作汽车。但这并不意味着您可以在维基百科中进行搜索和替换并将“汽车”一词的所有用法更改为“1995 Ford Escort”并且文章仍然正确!

事实上,你不能使用C<B>的原因其中 C<A>预期是因为这样做违反了 Liskov 替换原则:

class A {}
class B : A {}
class D : A {}
class C<T>
{
  public T M(T t) { ... }
}
...
C<B> cb = new C<B>();
C<A> ca = cb; // Suppose this were legal
ca.M(new D());

您可以使用 D 类型的对象任何你可以使用 A 的地方,但是 ca真的是cb , 你不能使用 D任何你可以使用 B 的地方!因此你不能使用 C<B>任何你可以使用 C<A> 的地方.

C# 4 及更高版本确实允许这种协变当编译器可以证明这样做是安全的。在网络上搜索 C# 协方差以获取详细信息;你会发现很多关于这个主题的文章。 (包括我的。)

关于c# - 为什么派生类的泛型会产生非派生类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19431491/

相关文章:

c++ - C++ 中灵活的类行为

java - 方法返回对象而不是在泛型方法中显式转换的类型

c# - 如何让组合框重新测量项目高度?

c# - 使用 asp.net mvc 为不同的用户类型提供不同的启动布局

c# - C#中的多线程序列化

c# - 如何在 .NET 中使用 RSA 和 SHA256 对文件进行签名?

php - 创建了多少个类的实例

oop - 这套 SOLID 原则是否缺少额外的 'D' ?

Java 通用返回类型问题

generics - 如何为涉及对中间局部变量的引用的闭包指定生命周期边界?