泛型(三)泛型类型和继承
泛型类型仍然是类型,所以它能从其他任何类型派生,使用一个泛型类型并指定类型实参时,实际是在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.