数组
Animal[] arrayAnimal = new Animal[3];
arrayAnimal[0] = new Cat("嘻嘻");
arrayAnimal[1] = new Cat("哈哈");
arrayAnimal[2] = new Cat("嘿嘿");
优点:在内存中连续存储。
缺点:创建时必须指定数组变量大小,两个元素之间添加元素比较困难。
集合
.Net Framwork提供了用于数据存储和检索的专用类,这些类统称为集合。大多数集合类实现相同的接口。ArrayList是其中常用的一种。引用System.Collection命名空间,它是使用大小可按需动态增加的数组实现IList接口。ArrayList的容量是ArrayList可以保存的元素数,ArrayList的默认初始容量是0。随着元素添加到ArrayList中,容量会根据需要通过重新分配自动增加。使用整数索引可以访问此集合中的元素。此集合中的索引从零开始。
IList arrayAnimal = new ArrayList();
arrayAnimal.Add(new Cat("嘻嘻")); //调用集合的add方法增加对象,其参数是object
arrayAnimal.Add(new Cat("哈哈"));
arrayAnimal.Add(new Cat("嘿嘿"));
foreach (Animal item in arrayAnimal) //遍历这个数组,让它们都Shout()
{
MessageBox.Show(item.shout());
}
arrayAnimal.RemoveAt(1);
arrayAnimal.RemoveAt(1); //调用集合的RemoveAt方法移除第2个和第3个对象
ArrayList优点:根据大小按需动态增加,不受事先设置其大小控制。可以随意地添加、插入或移除某一范围元素,比数组方便。
ArrayList缺点:它不是类型安全的。ArrayList不管你是什么对象都是接受的,因为在它眼里所有的元素都是Object。如果你写arrayAnimal.Add(123);编译时没问题,运行到foreach(Animal item in arrayAnimal)就会报错。另外ArrayList存放int、string、struct数据的时候,还存在一个装箱、拆箱的问题,值类型与引用类型发生转换,值转引用叫装箱;引用转值称拆箱;两种类型的内存处理机制是不同的,因此不能直接拿来用。即:使用ArrayList就意味着都需要将值类型装箱为object对象;使用集合元素的时候,还需要执行拆箱操作,从对象中提取值类型。装箱和拆箱会带来很大的性能损耗。
//装箱,把值类型打包到Object引用类型的一个实例中
int i = 123;
object o = (object) i; //整型变量i被装箱并赋值给对象o
//拆箱,从对象中提取值类型
o = 123;
i = (int) o; //对象o拆箱并将其赋值给整型变量i
相对于简单的赋值而言,装箱和拆箱过程需要进行大量的计算。对值类型进行装箱时,必须分配并构造一个全新的对象。其次,拆箱所需的强制转换也需要进行大量的计算。
泛型
泛型是具有占位符(类型参数)的类、结构、接口和方法,这些占位符是类、结构、接口和方法所存储或使用的一个或多个类型的占位符。泛型集合类可以将类型参数用作它所存储的对象的类型的占位符;类型参数作为其字段的类型和其方法的参数类型出现。【MSDN】
使用时,需要引用命名空间System.Collection.Generic,该类使用大小可按需动态增加的数组实现IList泛型接口。用法上就是在IList和List后面加”<数据类型>”,其中<>里面就是你需要指定的集合的数据或对象类型。解决了ArrayList类型不安全的问题。
IList<Animal> arrayAnimal = new List<Animal>(); //IList<Animal>表示此集合变量只能接受Animal类型
arrayAnimal.Add(new Cat("嘻嘻"));
arrayAnimal.Add(new Cat("哈哈"));
arrayAnimal.Add(new Cat("嘿嘿"));
通常情况下,都建议使用泛型集合,类型安全,对于值类型元素不必进行装箱。