之前两篇文档讲述了C#中的面向对象的概念,其实这个概念对于很多种语言都是通用的,只不过每种语言具体实现的过程方法不一样,比如Java、C++、python等,这些都是很流行的面向对象的语言在编程语言排行榜中都是属于前几名的。面向对象中比较难以理解的就是多态的概念,多态我将留到后面的章节去讲,现在继续先学习好基本的一些语法理解好语意才能更好的理解。
数组
数组顾名思义就是一组同类数据元素的集合,数组不单单是数字的集合,可以是多种类型的,但是集合中元素必须是同一种数据类型,那么什么是同类数据的元素呢?在第一篇中有介绍C#中15中最常用的数据类型(类型还可以自己扩展),每种类型有最大值最小值,每一个值就相当于是一个元素了,打个比如int类型的数组那就只可以存储int的类型的元素,如果在int类型中存储string类型,那么编译器或报错,数组在C#中是最早出现的,在内存中是连续存储的,所以它的索引速度非常快,下面来看一下如果声明一个数组。
这里使用int类型:
1 //创建一个大小为3的数组 2 3 int[] intArray = new int[3]; 4 5 //赋值 6 7 intArray[0] = 1; 8 9 intArray[1] = 2; 10 11 intArray[2] = 3; 12 13 //修改 14 15 intArray[2]=4;
但是在数组中存在一些不足的地方,比如在数组的两个数据之间插入数据是很麻烦,在插入数组后面的所有元素都要往后退一位,而且在声明数组的时候必须指定数组的长度,数组的长度过长,会造成内存的浪费,过长也会造成数据溢出的错误,针对数组的这些缺点,又推出了ArrayList对象来克服这些缺点。
ArrayList
在命名空间System.Collection中,ArrayLis存储的对象元素是动态去分配的,根据需求去进行相应的扩容和收缩空间,所以在声明ArrayLis对象时并不需要去指定它的长度。
1 //声明一个ArrayList对象 2 ArrayList arrayList = new ArrayList(); 3 4 //新增数据 5 arrayList.Add(123); 6 arrayList.Add("Leon"); 7 8 //修改数据 9 arrayList[1] = 32; 10 11 //删除 12 arrayList.Remove(0); 13 14 //插入数据 15 arrayList.Insert(0, 445);
从上面的例子中ArrayList好像是解决上面数组遗留下来的问题,当时当你实际编译的时候就会遇到异常了,如果有在编译器上实习输入代码编译的同学会发现,arrayList.Add( )这个方法接受的是一个object的类型,那么当我在arrayList[0],这个位置赋值的时候就会出现一个装箱拆箱所带来的性能损耗,而且在我第二次使用Add时插入的是一个string类型的变量,那么同一个数组中出现两种不一样的数据类型,并且在编译的时候是正常的,所以在编译时不能检查类型,在运行中就会出现错误。装箱拆箱实际上就是object类型和其它类型之间的数据转换所带来的性能损耗,具体过程可以在网上查下资料。
泛型List
因为ArrayList存在不安全类型与装箱拆箱的缺点,所以后面微软又推出了泛型,List类和ArrayList类的用法相似,但是最关键的地方在于 List声明集合的时候必须要指定数据对象的类型。
1 //声明List集合对象 2 List<string> listString = new List<string>(); 3 4 //增加 5 listString.Add("leon"); 6 7 //修改 8 listString[0] = "newLeon"; 9 10 //删除数据 11 listString.RemoveAt(0);
这里可以看到,List和ArrayList的用法差不多,区别就在于List在声明的时候必须要指定数据对象的类型,这样如果尝试在listString中插入int类型的值编译器就会报错,在编译时就可以避免一个类型安全的问题,和装箱拆箱带来的性能损耗。
小结:
数组的存储容量是固定的,每次只能对一个值去进行操作,而且在两个值之间插入一个元素的话很麻烦,不方便操作。
ArrayList中虽然定义好的一套方法可以很方便的去操作数组,很好的删除、插入元素,但是由于装箱拆箱的过程会浪费很多资源,而且编译时没有提供一个安全类型的检查,使得在一个有int类型的数组中允许插入其它类型的,比如string,这样虽然在编译时不会报错,但是在运行时会发生异常。
泛型List,泛型int类型是强类型,在编译时会检查类型,并且减少装箱拆箱带来的损耗。
这里注意数组可以是多维度的但是,ArrayList和List始终只具有一个维度。