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

Yos*_*ari 1 c# oop generics polymorphism

让我们假设我们有两个类A,B其中B来自A.

class A
{
}

class B : A
{
}

class C<T>
{
}
Run Code Online (Sandbox Code Playgroud)

现在,C<B> 不获得C<A>.

这让我有点困惑,因为我强调我用A做的"一切",我可以用B做.我确信我错过了一些东西,因为它似乎与OOP的基础相矛盾.

那有什么具体的理由和榜样吗?

编辑:

我读过许多类似的帖子: 在C#中,为什么List <string>对象不能存储在List <object>变量中

当值类型可以相互转换时,为什么我不能将一个值类型的字典转换为另一个值类型的字典?

从IEnumerable <Object>转换为IEnumerable <string>

但是在每个帖子中,答案都集中在特定的类/数据结构中,并使这个特定的代码工作,而不是为什么它一般不可能?

Eri*_*ert 9

虽然我可以用A做"一切",我可以用B做.我确信我错过了一些东西,因为它似乎与OOP的基础相矛盾.

让我们首先说明你提到的基本原则.来自维基百科:

如果S是T的子类型,则类型T的对象可以用类型S的对象替换,而不改变该程序的任何期望属性.

你缺少的是关键词:对象.

您也可以替换的对象类型的B任何地方,对象类型A是必需的.但事实并非如此,您可以使用该类型 A执行所有类型的操作 B.如果有人问你要一辆车而你给他们一辆1995年的福特护航,那么他们就可以把它用作汽车.但这并不意味着你可以在维基百科中进行搜索和替换,并将"car"这个词的每个用法改为"1995 Ford Escort",并且文章仍然是正确的!

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

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());
Run Code Online (Sandbox Code Playgroud)

您可以在D任何可以使用的地方使用类型的对象A,但ca实际上是cb,并且您不能在D任何可以使用的地方使用B!因此,您无法使用C<B>任何可以使用的地方C<A>.

当编译器证明这样做是安全的时, C#4及更高版本允许这种协方差.有关详细信息,请在C#covariance上进行网络搜索; 你会找到很多关于这个主题的文章.(包括我的.)


归档时间:

查看次数:

303 次

最近记录:

12 年,1 月 前