泛型类型仍然是类型,所以它能从其他任何类型派生,使用一个泛型类型并指定类型实参时,实际是在CLR中定义一个新的类型对象,新的类型对象是从泛型类型派生自的那个类型派生的,换言之,由于List<T>是从Object派生的,所以List<String>和List<Guid>也从Object派生。
类似地,由于DictionaryStringKey<TValue>派生自Dictionary<String,TValue>所以DictionaryStringKey<Guid>派生自Dictionary<String,Guid>,类型实参的指定和继承层次结构没有任何关系--理解这一点,有助于判断哪些转型是能够进行的,哪些转型是不能进行的。
继承
假定像下面这样定义一个链表节点类
internal sealed class Node<T>{
public T m_data;
public Node<T> m_next;
public Node(T data):this(data,null){}
public Node(T data,Node<T> next){
m_data=data;
m_next=next;
}
public override ToString(){
return m_data.ToString()+
((m_next!=null)?m_next.ToString():null);
}
}
static void Main(string[] args)
{
Node<Char> head = new Node<Char>('C');
head = new Node<Char>('B', head);
head = new Node<Char>('A', head);
Console.WriteLine(head.ToString());
}
输出:ABC
在这个Node类中,对于m_next字段引用的另一个节点来说,它的m_data字段必须包含相同的数据类型,意味着在链表包含的节点中,所有数据项都必须具有相同的类型(或派生类型),不能包含即有DateTime类型又有String 类型
改进
思路:定义一个非泛型的Node基类,在定义一个泛型TypedNode类(用Node类作为基类),这样依赖就可以创建一个链表,每个节点都可以是一种具体的数据类型(非Object类型),同时防止装箱,有点递归的意思。
internal class Node{
protected Node m_next;
public Node(Node next) {
m_next = next;
}
}
internal sealed class TypeNode<T> : Node {
public T m_data;
public TypeNode(T data) : this(data, null) { }
public TypeNode(T data, Node next)
: base(next)
{
m_data = data;
}
public override string ToString()
{
return m_data.ToString() +
((m_next != null) ? m_next.ToString() : null);
}
}
程序入口:
Node head = new TypeNode<Char>('.');
head = new TypeNode<DateTime>(DateTime.Now, head);
head = new TypeNode<String>("Today is ", head);
Console.WriteLine(head.ToString());
程序输出:
Today is 2012-11-23 16:33:14.