好吧,当你写一门课时C<T>,一切都是关于C,而不是T。T只是提供用于表示特殊C<>类型的类型信息。C<>有自己的实现,与T. 当你写:
var c = new C<int>();
变量的行为c完全按照你在课堂上写的C<>。无论Tisint还是string什么,它的行为都是一样的。
另请注意,编写为 like 的类C<S>是一种特殊类型,与C<T>另一种类型不同,因为所有行为都受到它的C-ness 的限制。我们永远不知道它是如何C<>编写的以及它将如何表现。所以你描述的方式不是泛型如何发挥作用。如果您有额外的课程,例如
class D<T> : C<T>
{
}
你可以写:
C<A> c = new D<A>();
你看,这又是可能的,因为C派生自D. 班级的左边很重要。这又是非法的:
C<A> c = new D<B>();
即使A派生自B,因为与of (甚至Cof )A没有关系,它是一个单独的类。DBCB
这种泛型多态性实际上是毫无意义的,当你认为C<A>它们是一种完全不同的类型时,C<B>尽管它们具有共同的行为。用另一个例子来说明,想想这个,一个类可以是多个类型的泛型。假设有
class C<S, T>
{
}
C<IList<A>, A>和怎么样C<IList<int>, B>?它们的类型是否具有可比性,因为这两个具有IList和A和B作为泛型类型?C<T>浇注料C<S, T>来自? 不,简而言之,这些是不同的类型。
现在如果你不想做任务
C<A> ca = new C<B>();
可能您可以编写自己的隐式转换器。
class C<T>
{
public static implicit operator C<T>(C<B> c)
{
type check, explode or return
}
}
//now you may write:
C<A> ca = new C<B>();
//or even
C<A> ca = new D<B>();
请注意,这并不意味着继承关系,而只是一种转换操作。
如果没有关于协变和逆变的信息(仅适用于接口和委托),则没有关于泛型的信息是不完整的。如果让这种情况发生,请参阅 OR Mapper 关于危险的回答。C# 允许这样做的一种情况是数组。可悲的是,这是一个破碎的设计。这在 C# 中是可能的
object[] o = new string[1];
o[0] = 1; //explosion
我很想详细说明,但我所做的任何事情都会使它变得多余。有关明确信息,请参阅Eric Lippert的出色回答。