.NET中的范型与集合

    在学习设计模式的时候,我们用到了范型,在VB.NET机房重构的时候,我们又用到了范型,感觉范型就像一个集合Collections,而且集合ArrayList()非常好用,它可以盛放许多类型的数据(里面涉及到了拆箱与装箱),那么,范型与ArrayList()又有什么渊源哪?下面我讲一下C#中的范型与集合ArrayList()的区别。

一、泛型简介:

泛型(Generic Type)是.NET Framework2.0最强大的功能之一。泛型的主要思想是将算法与数据结构完全分离开,使得一次定义的算法能作用于多种数据结构,从而实现高度可重用的开发。通过泛型可以定义类型安全的数据结构,而没有必要使用实际的数据类型,这将显著提高系统性能并得到高质量的代码(因为可以重用数据处理算法,没有必要复制类型特定的代码。

二、范型与ArrayList()的渊源关系

拿C#编程为例,C# 是一个类型安全的语言,类型安全允许编译器(可信赖地)捕获潜在的错误,而不是在程序运行时才发现(不可信赖地,往往发生在你将产品出售了以后!)。因此,在C#中,所有的变量都有一个定义了的类型;当你将一个对象赋值给那个变量的时候,编译器检查这个赋值是否正确,如果有问题,将会给出错误信息。

在.Net 1.1 版本(2003)中,当你在使用集合时,这种类型安全就失效了。由.Net 类库提供的所有关于集合的类全是用来存储基类型(Object)的,而.Net 中所有的一切都是由Object基类继承下来的,因此所有类型都可以放到一个集合中。于是,相当于根本就没有了类型检测。更糟的是,每一次你从集合中取出一个Object,你都必须将它强制转换成正确的类型(拆装箱)这一转换将对性能造成影响,并且产生冗长的代码(如果你忘了进行转换,将会抛出异常。更进一步地讲,如果你给集合中添加一个值类型(比如,一个整型变量),这个整型变量就被隐式地装箱了(再一次降低了性能),而当你从集合中取出它的时候,又会进行一次显式地拆箱(又一次性能的降低和类型转换)。

在公共语言运行库和C# 语言的早期版本中,通用化是通过在类型与通用基类型Object 之间进行强制转换来实现的,泛型提供了针对这种限制的解决方案。通过创建泛型类,您可以创建一个在编译时类型安全的集合。使用非泛型集合类的限制可以通过编写一小段程序来演示,该程序利用.NET Framework 基类库中的ArrayList 集合类。ArrayList
是一个使用起来非常方便的集合类,无需进行修改即可用来存储任何引用或值类型。

个人理解:当我们用C#或者VB.NET编写的代码想让机器执行时,是一种高级语言向低级语言转化的过程,由C#编写的代码转化成机器语言,这样机器才可以直接执行。执行的过程是:编译器将源码转化为微软中间语言MSIL,然后再由公共语言运行时(CLR)转化成机器语言。(如果不理解,可以点击此超链接)这样,机器就可以直接执行我们编写的代码了。如果不理解,可以看我的博客.NET框架。当编译器对源码进行编译时,就实现了上面所说的在编译阶段检查错误的功能。

范型与集合相比,有以下几个优点。

1、性能

对值类型使用非泛型集合类,在把值类型转换为引用类型,和把引用类型转换为值类型时,需要进行装箱和拆箱操作。装箱和拆箱的操作很容易实现,但是性能损失较大。假如使用泛型,就可以避免装箱和拆箱操作。

ArrayList list=new ArrayList();
 list.Add(20);            //装箱,list存放的是object类型元素,须将值类型转化为引用类型
 int i=(int)list[0];     //拆箱,list[0]的类型是object,要赋值就得把引用类型转化为值类型

如果换成泛型编程,就不会有装箱和拆箱的性能损失。

<span style="font-family:KaiTi_GB2312;font-size:18px;">List<T> list=new List<int>();
list.Add(20);    //因为指定了用int来实例化,因此不必装箱
int i=list[0];    //同样地,访问时也不需要拆箱,可以直接接受,不需要转化。</span>

  2、类型安全。

与ArrayList类一样,如果使用对象,可以在这个集合中添加任意类型。如果使用非泛型编程,如下代码,就有可能在某些情况下会发生异常。注意:编译时不出错,但运行时有错。

<span style="font-family:KaiTi_GB2312;font-size:18px;"> ArrayList list=new ArrayList();
 list.Add(20);
 list.Add("string");
 foreach(int i in list)
 {
        Console.WriteLine(i);    //这里会有个异常,因为并不是集合中的所有元素都可以转化为int
 }</span>

如果该用泛型编程,则可以避免这种异常,让编译器检查出错误。

<span style="font-family:KaiTi_GB2312;font-size:18px;">List<int> list=new List<int>();
list.Add(20);
lsit.Add("string");   //编译时报错,只能报整数类型添加到集合中
</span>

3、二进制代码重用

  泛型可以定义一次,用许多不同的类型实例化,不需要像C++模板那样访问源代码。泛型可以在一种语言中定义,在另一种.NET语言中使用。

4、代码的扩展

  因为泛型类的定义会放在程序集中,所以用某个类型实例化泛型泛型类不会在IL(微软中间语言)代码中复制这些类。但是,在JIT编译器把泛型类编译为内部代码时,会给每个值类型创建一个新类。引用类型共享同一个内部类的所有实现代码。这是因为引用类型在实例化的泛型类中只需要4字节的内存单元(32位系统),就可以引用一个引用类型。值类型包含在实例化的泛型类的内存中。而每个值类型对内存的要求都不同,所以要为每个值类型实例化一个新类。

以上是本人对范型和集合做了一点点的比较,总的来说,利用范型可以定义类型安全的数据结构(编译器编译时检查错误),能提高代码的性能(减少拆装箱) ,可以复用,当然,代码扩展。

时间: 2025-01-23 01:17:30

.NET中的范型与集合的相关文章

Swift快速入门之延迟调用与范型

defer defer 就像当于其它语言中的final代码块,它在函数中所有其它代码之后,函数返回之前运行.不论函数有没有抛出错误,它的代码都能运行.如下: var fridgeIsOpen = false let fridgeContent = ["milk", "eggs", "leftovers"] func fridgeContains(itemName: String ) -> Bool { fridgeIsOpen = true

使用预处理命令实现C的范型编程

一.引言 Generic programming is a style of computer programming in which algorithms are written in terms of types to-be-specified-later that are then instantiated when needed for specific types provided as parameters. 范型编程在1973年的ML语言中首次提出,是在C语言之后诞生的,你可以轻

java范型集合中的成员排序

范型集合中的类是JsonObject,不是自定义类,如果是自定义类就直接取要比较的字段值. 1 ArrayList<JSONObject> TList = new ArrayList<JSONObject>(); 2 3 for(int i=0;i<10000;i++) 4 { 5 JSONObject object=new JSONObject(); 6 Random rand = new Random(); 7 int randNum = rand.nextInt(200

Epplus下的一个将Excel转换成List的范型帮助类

因为前一段时间公司做项目的时候,用到了Excel导入和导出,然后自己找了个插件Epplus进行操作,自己将当时的一些代码抽离出来写了一个帮助类. 因为帮助类是在Epplus基础之上写的,项目需要引用Epplus.dll.自己基础不是很扎实,有问题的地方欢迎指导. 1.用法,默认excel第一列是头部信息. public class UserInfo : XlsRow { public int id { get; set; } public string username { get; set;

Swift之旅(七)范型

在尖括号里面写上名称就可以使函数或者类型变为范型. func repeat<Item>(item: Item, times: Int) -> [Item] { var result = [Item]() for i in 0..<times { result.append(item) } return result } repeat("knock", 4) 不仅可以定义范型函数和方法,还可以定义范型类.枚举和结构体. // 重新实现 Swift 标准类库的可选类

七周七语言:理解多种编程范型pdf

下载地址:网盘下载 作者简介  · · · · · · 作者简介: Bruce A. Tate RapidRed公司总裁,该公司主要为Ruby轻量级开发提供咨询.他曾任职于IBM公司,并担任过多家公司的客户解决方案总监和CTO.著作有十余本,包括荣获Jolt大奖的Better, Faster, Lighter Java. 译者简介: 戴玮 80后宅男,中科院自动化所在读博士,热爱机器学习与计算机视觉.编程喜C#.Ruby.Haskell而厌Java. 白明 Neusoft某开发部技术总监,拥有多

由Cannot create a generic array of ArrayList&lt;xx&gt;引出的学习--Java范型

最近在用Java写某个程序时希望写出一个包括ArrayList<xx>的数组 自己定义如下: ArrayList<edge>[] edges = new ArrayList<edge>()[10]; 然后编译器报错如下: Cannot create a generic array of ArrayList<edge>; 在C++里可以这样比较方便的定义:  vector<edge> a[100]; 在Java里报错,查询了一下,见已经有人在sta

利用传入的Type类型来调用范型方法的解决方案

起因:自定义一个GridView控件,其数据源来源于一个通用方法Get<T>(),根据你传入的T到数据库中得到相应的数据,问题是定义GridView控件时没法在界面端设置使用泛型,只能在每个使用这个GridView控件时绑定数据.如果你没看懂这个起因也没关系,我们用一段代码来描述一下问题:我希望使用的是从外边传过来的类型tt来调用test1范型方法 class Program     {         static void Main(string[] args)         {    

分布式计算(一)基本范型

对于分布式的概念既模糊又有些理解,总是无法很好的把握,似乎与我们工作无关,但又天天在用,  究竟什么是分布式, 它能做什么?从那下手,网上可以查到很多,都使我越来越糊涂,大概是分布式计算.分布式存储.分布式缓冲等.日日梳理这些 模糊的东西,希望能有一天,能从这里走出一条光明的路. 1. 根据分布式计算抽象层次和封装层次的不同,可以将分布式的计算范型分为以下几类: 2.消息传递范型 消息传递(Message Passing) 范型利用网络API,完成将用户请求进行打包.传送和解包的工作,必要时还要