假设我们有两个类 A
和 B
其中 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
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/