泛型及其继承和同一性
2015-06-18 10:16
232 查看
泛型,面向对象编程的一种编程方式,可以很好地进行代码重用(尤其是‘算法重用’),极大地提高了开发效率。换言之,泛型可以派生出一个类,让它继承基类的所有能力。派生类只需要重写虚方法,或添加一些新方法,就可以定制派生类的行为。
算法重用,简单地说,开发人员先定义一个算法,比如排序,搜索等,但定义算法的开发人员并不设定该算法要操作什么数据类型,该算法可广泛地应用于不同类型的对象。然后另一个开发人员只要指定了算法要操作的具体操作类型,就可以开始使用这个现成的算法了。
泛型类型也是类型,所以能从其他类型派生。使用一个泛型类型,并指定类型实参时,实际是在CLR中定义一个新的类型对象,新的类型对象是从泛型类型派生自的那个类型派生的。换言之,List<T>是从Object派生的,所以List<String>也是从Object派生的。
看两段代码
示例1:
示例1中,对于m_next字段引用的另一个节点来说,它的m_data字段必须包含相同的数据类型。这意味着在链表包含的节点中,所有数据项都必须具有相同的数据类型。当然,若到处都用Node<Object>,那么确实可以做到,但会丧失编译时的类型安全性,而且值类型会被装箱。
所以一个更好的办法是定义一个非泛型Node基类,再定义一个TypedNode类(Node类作为基类)。这样一来,就可以创建一个链表,其中每个节点都可以是一种具体的数据类型(不能是Object),同时获得编译时的类型安全性,并防止值类型装箱。具体实现参考示例2。
示例2:
简单提及一下同一性,C#提供了一种方式,允许使用简化的语法来引用一个泛型封闭类型,同时不会影响类型的相等性-using指令。例如using TStringNode = 命名空间.NodeDemo<T>;这样TStringNode 和 命名空间.NodeDemo<T> 类型是一样的。若使用继承方式,则会影响类型同一性。
算法重用,简单地说,开发人员先定义一个算法,比如排序,搜索等,但定义算法的开发人员并不设定该算法要操作什么数据类型,该算法可广泛地应用于不同类型的对象。然后另一个开发人员只要指定了算法要操作的具体操作类型,就可以开始使用这个现成的算法了。
泛型类型也是类型,所以能从其他类型派生。使用一个泛型类型,并指定类型实参时,实际是在CLR中定义一个新的类型对象,新的类型对象是从泛型类型派生自的那个类型派生的。换言之,List<T>是从Object派生的,所以List<String>也是从Object派生的。
看两段代码
示例1:
internal sealed class NodeDemo<T> { public T m_data; public NodeDemo<T> m_next; public NodeDemo(T data, NodeDemo<T> next) { m_data = data; m_next = next; } public NodeDemo(T data) : this(data, null) { } public override string ToString() { return m_data.ToString() + ((m_next != null) ? m_next.ToString() : null); } } // 调用代码 static void Main(string[] args) { // 节点类型都是 Char NodeDemo<Char> head = new NodeDemo<Char>('C'); head = new NodeDemo<Char>('B', head); head = new NodeDemo<Char>('A', head); Console.WriteLine(head.ToString()); Console.ReadKey(); } // 代码执行 显示‘ABC’
示例1中,对于m_next字段引用的另一个节点来说,它的m_data字段必须包含相同的数据类型。这意味着在链表包含的节点中,所有数据项都必须具有相同的数据类型。当然,若到处都用Node<Object>,那么确实可以做到,但会丧失编译时的类型安全性,而且值类型会被装箱。
所以一个更好的办法是定义一个非泛型Node基类,再定义一个TypedNode类(Node类作为基类)。这样一来,就可以创建一个链表,其中每个节点都可以是一种具体的数据类型(不能是Object),同时获得编译时的类型安全性,并防止值类型装箱。具体实现参考示例2。
示例2:
internal class Node { protected Node m_next; public Node(Node next) { m_next = next; } } internal sealed class TypedNode<T> : Node { public T m_data; public TypedNode(T data, Node next) : base(next) { m_data = data; } public TypedNode(T data) : this(data, null) { } public override string ToString() { return m_data.ToString() + ((m_next != null) ? m_next.ToString() : null); } } // 调用代码 static void Main(string[] args) { // 节点类型都不一样 Node head = new TypedNode<Char>('.'); head = new TypedNode<DateTime>(DateTime.Now, head); head = new TypedNode<String>("Today is ", head); Console.WriteLine(head.ToString()); Console.ReadKey(); } // 代码执行 显示‘Today is 2015-6-18 10:00:00.’
简单提及一下同一性,C#提供了一种方式,允许使用简化的语法来引用一个泛型封闭类型,同时不会影响类型的相等性-using指令。例如using TStringNode = 命名空间.NodeDemo<T>;这样TStringNode 和 命名空间.NodeDemo<T> 类型是一样的。若使用继承方式,则会影响类型同一性。
相关文章推荐
- umask码和文件权限
- C# WPF ASP.net 上传多文件和数据
- 解析哈希表
- Google Code Jam 2015 R2 C
- jQuery全屏滚动插件fullPage.js
- Class.forName加载mysql驱动总是产生ClassNotFoundException异常
- c++ builder 俩种不同风格的窗体
- java字符串
- idea导入项目出错
- 将本地html文件拖到IE8浏览器无法打开,直接弹出一个下载的对话框
- iOS va_list,va_start,va_end
- 希尔排序
- CRC32算法详细推导(3)
- CRC算法详解(2)
- SYSTEMTAP安装
- UIModalPresentationFormSheet resizing view
- php---本地开发及测试环境搭建(Wamp)
- 开源bug管理工具-Cynthia
- HTML5 section、article和div区别
- 自动处理NSLog