.NET泛型技术的研究与分析

  • 来源:中文信息
  • 关键字:.NET,泛型,程序设计
  • 发布时间:2015-01-06 13:39

  摘 要:本文泛型的概述、优点、使用安全、在.NET程序设计中的应用这几个方面内容进行分析,以供参考。

  关键词:泛型 .NET 概述 应用 分析 发展

  中图分类号:TP312 文献标识码:A 文章编号:1003-9082(2015)01-0001-02

  一、前言

  随着计算机技术的快速发展和进步,泛型技术深化发展,并在计算机编程中广泛使用。

  二、泛型技术概述

  泛型(generics,genericity)又称为「参数化类型(parameterizedtypes)」或模板(templates),或所谓「参数式的多型(parametricpolymorphism)」。主要是一种类型代换(typesubstitution)概念,是和继承(inheritance)不同而互补的一种组件复用机制。泛型技术最直接被联想到的用途之一就是建立资料群集(collections),允许使用者将某些特定类型的资料(物件)置入其中,并于取出时明确知道元素的类型,无需做(向下)转型动作。假设某个泛型程序库提供list,你便可以明确宣告一个内含int或double或Shape(使用者自定类型)元素的list(这是C++应用型式),或明确宣告一个内含Integer元素的list(这是Java应用型式),如下:

  listiList;//inC++

  LinkedListiList=newLinkedList();//inJava

  三、泛型的优点

  1.安全

  C#是一个类型安全的语言,类型安全允许编译器(可信赖的)捕获潜在的错误,而不是在程序运行时才发现(不可信赖的).在cIR1.0中,当使用集合时,这种类型安全就失效了:由.NET类库提供的集合类全是存储基类型(Ob—ject)的,而.NET中所有的一切都继承于Object,因此所有类型都可以放到一个集合中,这相当于根本就没有了类型检测。

  下面的代码也正好说明了这个问题。

  ArrayList list = new ArrayList();

  list.Add(1O0);list.Add(“test”);list.Add(new object());

  foreaeh(int i in list)//引发运行期错误

  Console.Write(i);

  可以往ArrayList里添加任何类型,也能通过编译,但是在接下来的使用中,由于字符串“test”和Object对象都不能转换为值类型int,这会抛出运行期错误,类型不再安全。

  2.性能

  泛型的一个主要优点是性能.如果对值类型使用普通的集合类,在把值类型转换为引用类型和把引用类型转换成为值类型时,程序会进行装箱和拆箱操作,性能损失比较大,操作迭代多次时尤其严重.而使用泛型能使程序在运行期间明确知道操作的对象的类型,可以减少拆箱和装箱的操作。

  四、泛型的使用和安全

  1.泛型的使用

  泛型最初出现在一些非面向对象的语言中,后来逐渐被引入面向对象的语言中。简单地说,泛型就是“类型参数化”,即实现方式与类型无关。实质上,泛型是面向对象设计和实现过程中的一种高效、安全地实现代码重用的编程思想。它包括2个方面:避免或减少了代码的重复编制;系统效率并未因此而降低。它要求代码均由编译器从一份通用代码自动拷贝而来,因此这份代码必须对所有类型都适用。

  由于日益增加的混合项目,程序员经常需要一种更好的手段复用和定制现存的基于组件的软件。为了达到这种高水平的代码复用,程序员通常使用称为泛型的特性。在Whidbey中,CLR包含一种类型安全的、高性能、编译时检查的泛型版本,它与C++中已有的模板和Java中将有的泛型在语法上区别很小,实现方式上却区别很大。泛型允许开发者一次性建立、测试和发布代码,但却能通过多种不同的数据类型来复用代码,而对应用软件的性能影响却微乎其微。与强类型的实现方式相比,CLR通过实现泛型可以减少代码臃肿,增强可读性和可维护性。Whidbey中同时支持泛型创建和泛型使用。

  2.类型安全

  在非泛型编程中,虽然所有的东西都可以作为Object传递,但是在传递的过程中免不了要进行类型转换,而类型转换在运行时是不安全的。使用泛型编程将可以减少不必要的类型转换,从而提高安全性。

  对于这一个问题,可以用一个普通的列表排序算法和一个泛型的列表排序算法进行比较。当用户向普通类型的排序列表中添加一个字符串的时候,字符串参数会被隐式的转换为Object同样,从排序列表里取出时,则必须运行时从对象引用强制转换到字符串引用。编译时,没有进行类型安全检查,从而较易导致运行时错误。相反,如果使用泛型算法,类型参数的类型被设置为string,则所有的添加和查找方法将使用string类型的引用。这样,在编译时就能指定和检查元素的类型。

  五、.NET泛型与Java泛型的对比

  Sun完全是在编译器中为Java实现泛型,而不是在JVM(Java虚拟机)中.Sun这样做的目的是为了防止因为使用了泛型而需要分发新的JVM.Java的实现使用了与c++中的“模板”和c#中的“泛型”相似的语法,其中包括类型参数和约束,但是由于它不区分对待值类型和引用类型,所以未修改的JVM不能为值类型支持泛型.所以Java中的泛型不具有c#那样的执行效率.Java编译器需要返回数据的时候,都会插人来自指定约束的自动向下转型(如果声踢了这样的一个转型的话),或者插人基本object类型(如果没有声明的话)。除此之外,Java编译器在编译时生成一个具体化的类型,它随即用于实例化任何已构造的类型.最后由于JVM没有提供对泛型的原生支持,所以在执行时无法确定一个泛型类型实例的类型参数,“反射”的其他应用也受到了严格的限制。

  六、泛型技术在.NET程序设计中的应用

  二叉树是一种常见的数据结构,用泛型的方法来构建一棵可用于多种类型的二叉树是非常容易的。对这棵树的要求是,在树的结点上可以存放任何类型的值,当然也应该包括左子树和右子树了。下面两段代码分别定义了二叉树的类和实现了二叉树的遍历,遍历的算法和树的定义在两个不同的类中实现,笔者在遍历中选择对一棵字符串类型的树进行操作。

  代码段一:

  public class Tree//以泛型方式定义二叉树

  {

  public TreeType m_data;//二叉树的结点

  public Tree l_child;//左子树

  public Tree r_child;//右子树

  public override string ToString()

  {

  return m_data.ToString();

  }

  public Tree(TreeType data,Tree left,Tree right)

  {

  m_data=data;

  l_child=left;

  r_child=right;

  }

  }

  代码段二:

  private TreeNode ShowTree(Tree root)//递归先根遍历

  {

  TreeNode node = new TreeNode(root.ToString());//处理二叉树的结点

  if(root.l_child!=null)//左子树

  node.Nodes.Add(ShowTree(root.l_child));

  if(root.r_child!=null)//右子树

  node.Nodes.Add(ShowTree(root.r_child));

  return node;

  }

  以往大至有两种方法解决这个问题:一种是定义一个不包括细节的树的基类,然后对于多种数据类型采用多种树子类来继承;另一种是用Object类型实现树,然后对于不同的数据类型进行装箱和拆箱的操作。与这两种方式相比,泛型的方法都有明显的优势。

  与第一种方法相比,泛型的方法所产生的代码要更简短很多,没有人愿意将同样的代码反复写上好几次,这样不仅费时费力,而且不好修改。从派生的角度来看,泛型类型及其所构造的类型之间没有派生关系,它们都是从System.Object直接派生出来的。

  与第二种方法相比,不同之处在于,Object表示任何类型,而Tree根本不指定类型,而是定义一个类型参数的占位符TreeType。当引用代码使用Tree时,才指定参数的数据类型。在笔者讨论例子里,选择了字符串来实现。如果需要某种其他类型的二叉树,比如整型(int),则可通过将它指定为TreeType的类型变量来实现。用泛型的方法实际上没有装箱和拆箱的动作,所以由此带来了如下两方面的好处:避免了装箱和拆箱这费时的操作,代码运行的速度会有一定的提高;避免了隐式或显式的强制类型转换,程序中所有数据类型方面的问题都会在编译时找到,而不会在运行时出现。

  七、结束语

  总之,信息化的发展将更加迅猛,更加先进的技术也将不断出现,在给人们生活带来便利的同时也将促进新的变革,获得更大的进步。

  参考文献

  [1]毕国锋.ASP.net技术的Web应用程序三层设计模型研究[J].黑龙江科技信息,2013,22(3):32-36

  [2]耿超.ASP.NET4.0网站开发实例教程[M].北京:清华大学出版社,2012.12

  文/孙建一

关注读览天下微信, 100万篇深度好文, 等你来看……