`
bbls
  • 浏览: 63442 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类

C#-ArrayList

阅读更多

如果要动态地改变数组所占用内存空间的大小,则需以数组为基础进一步抽象,以实现这个功能。以图2.2的学生宿舍为例,为了使A班的所学生住在连续的宿舍内,可以把A班的学生全部搬迁到连续的5间空宿舍内。其效果如图2.6所示:

现实中,为了让一个班新加入的10个学生能跟原来的学生住在一起而把班级整体搬迁,这样的做法显示不合适,因为搬迁的成本太高。但在计算机中,内存成片区域间的拷贝成本是非常低的,这样的解决方案是合理可行的。

但是这个解决方案还存在问题,如果一个班级频繁地有新学生加入,为了保证学生能住在连续的宿舍内,整个班级就不得不频繁地搬迁。可以采用以空间换时间的做法来解决这个问题,在学生每次搬迁时,都让班级宿舍的数量是原来的两倍。也就是说,如果原来一个班级有4间宿舍,搬迁后就变为8间,再次搬迁则变为16间。如图2.2所示,A班的宿舍为201208206208这三间宿舍做为本班备用宿舍,不再允许其他班级的学生搬入。

C#中的ArrayList正是采用上述方法来动态改变数组大小的。ArrayList又被称为动态数组,它的存储空间可以被动态改变,同时还拥有添加、删除元素的功能。

下面列出了ArrayList的部分核心代码:

ArrayList.cs

1   using System;

2   namespace LinearList

3   {

4       public class ArrayList

5       {

6           // 成员变量

7           private const int _defaultCapacity = 4; //默认初始容量

8           private object[] _items; //用于存放元素的数组

9           private int _size; //指示当前元素个数

10          //当元素个数为零时的数组状态

11          private static readonly object[] emptyArray = new object[0];

12          // 方法

13          public ArrayList() //默认构造方法

14          {   //这样做可以避免元素个数为零时的访问出错

15              this._items = emptyArray;

16          }

17          //指定ArrayList初始容量的构造方法

18          public ArrayList(int capacity)

19          {

20              if (capacity < 0)

21              {   //当容量参数为负数时引发异常

22                  throw new ArgumentOutOfRangeException("capacity",

23                      "ArrayList指定的初始容量不能为负数");

24              }

25              //按照capacity参数指定的长度的值初始化数组

26              this._items = new object[capacity];

27          }

28          //添加一个方法

29          public virtual int Add(object value)

30          {   //当空间满时

31              if (this._size == this._items.Length)

32              {   //调整空间

33                  this.EnsureCapacity(this._size + 1);

34              }

35              this._items[this._size] = value; //添加元素

36              return this._size++; //使长度加

37          }

38          //动态调整数组空间

39          private void EnsureCapacity(int min)

40          {

41              if (this._items.Length < min)

42              {   //空间加倍

43                  int num = (this._items.Length == 0) ?

44                      _defaultCapacity : (this._items.Length * 2);

45                  if (num < min)

46                  {

47                      num = min;

48                  }

49                  //调用Capacityset访问器以按照num的值调整数组空间

50                  this.Capacity = num;

51              }

52          }

53          //在指定索引入插入指定元素

54          public virtual void Insert(int index, object value)

55          {

56              if ((index < 0) || (index > this._size))

57              {

58                  throw new ArgumentOutOfRangeException("index", "索引超出范围");

59              }

60              if (this._size == this._items.Length)

61              {   //当空间满时调整空间

62                  this.EnsureCapacity(this._size + 1);

63              }

64              if (index < this._size)

65              {   //插入点后面的所有元素向后移动一位

66                  Array.Copy(this._items, index,

67                      this._items, index + 1, this._size - index);

68              }

69              this._items[index] = value; //插入元素

70              this._size++; //使长度加

71          }

72          //移除指定索引的元素

73          public virtual void RemoveAt(int index)

74          {

75              if ((index < 0) || (index >= this._size))

76              {

77                  throw new ArgumentOutOfRangeException("index", "索引超出范围");

78              }

79              this._size--; //使长度减

80              if (index < this._size)

81              {   //使被删除元素后的所有元素向前移动一位

82                  Array.Copy(this._items, index + 1,

83                      this._items, index, this._size - index);

84              }

85              this._items[this._size] = null; //最后一位空出的元素置空

86          }

87          //裁减空间,使存储空间正好适合元素个数

88          public virtual void TrimToSize()

89          {

90              this.Capacity = this._size;

91          }

92          // 属性

93          public virtual int Capacity //指示ArrayList的存储空间

94          {

95              get

96              {

97                  return this._items.Length;

98              }

99              set

100             {

101                 if (value != this._items.Length)

102                 {

103                     if (value < this._size)

104                     {

105                         throw new ArgumentOutOfRangeException("value", "容量太小");

106                     }

107                     if (value > 0)

108                     {   //开辟一块新的内存空间存储元素

109                         object[] destinationArray = new object[value];

110                         if (this._size > 0)

111                         {   //把元素搬迁到新空间内

112                             Array.Copy(this._items, 0,

113                                 destinationArray, 0, this._size);

114                         }

115                         this._items = destinationArray;

116                     }

117                     else //最小空间为_defaultCapacity所指定的数目,这里是

118                     {

119                         this._items = new object[_defaultCapacity];

120                     }

121                 }

122             }

123         }

124         public virtual int Count //只读属性,指示当前元素个数

125         {

126             get

127             {

128                 return this._size;

129             }

130         }

131         public virtual object this[int index] //索引器

132         {

133             get //获取指定索引的元素值

134             {

135                 if ((index < 0) || (index >= this._size))

136                 {

137                     throw new ArgumentOutOfRangeException("index", "索引超出范围");

138                 }

139                 return this._items[index];

140             }

141             set //设置指定索引的元素值

142             {

143                 if ((index < 0) || (index >= this._size))

144                 {

145                     throw new ArgumentOutOfRangeException("index", "索引超出范围");

146                 }

147                 this._items[index] = value;

148             }

149         }

150     }

151 }

上述代码通过在一个数组(第8行代码的成员变量_items)的基础上做进一步抽象,构建了一个可动态改变空间的顺序表ArrayList,并实现了一些基础操作,下面对之进行一一介绍。

1.    初始化

这里实现了2种初始方法,第一种为1316行代码,它把顺序表空间初始化为一个0长度数组。这样做的目的是为了调用方便。做为成员变量的object类型数组_items默认会被初始化为null,如果不把它初始化为0长度数组,在使用代码 ArrayList arr = new ArrayList() 来创建ArrayList后试图访问它的Count属性将会导致错误发生。

第二种初始化方法为1827行代码,它根据capacity参数所指定的值来初始化_items数组的长度,如果初始化一个长度为100ArrayList数组可以使用如下代码:

ArrayList arr = new ArrayList(100)

当可以预见ArrayList所操作的大概元素个数时,使用这种方法可以在一定程序上避免数组重复创建和数据迁移,以提高性能和减少内存垃圾回收的压力。

2.    动态改变存储空间操作

3952行的EnsureCapacity(int min)方法用于空间不足时使空间加倍,从代码:

int num = (this._items.Length == 0) ? _defaultCapacity : (this._items.Length * 2);

可以得知,当元素个数为0是,空间增长为4,否则将翻倍。改变空间大小的代码是在Capacity属性中的set访问器中实现的(代码99122行)。代码

object[] destinationArray = new object[value];

创建了一个新的object数组,它在内存中开辟了一个新的空间用于存放元素。代码

Array.Copy(this._items, 0, destinationArray, 0, this._size);

_items数组中的元素全部拷贝到新数组destinationArray中,可以把它理解为数据搬新家。最后通过

this._items = destinationArray;

使用于存放数据的成员变量_items指向新的数组对象destinationArray

8891TrimToSize()方法用于裁减多余空间,实际的裁减操作也是在Capacity属性中的set访问器中实现。这个操作也会导致数组的重新创建和数据迁移,建议一般情况下不使用此操作,除非集合中的剩余空间很多。

3.    元素的读写操作

131149行代码实现了一个索引器,这样就可以使用中括号加索引号来读取和给元素赋值,使ArrayList的使用看上去和数组很相似。

4.    元素的添加和插入操作

2937行的Add(object value)方法实现了添加元素的功能。元素添加在集合的末尾,成员变量_size用于指示当前元素个数,它总是指向集合中的最后一个元素。

5471Insert(int index, object value)方法用于在指定索引处插入一个元素。为了保证顺序表中的每个元素物理上相邻,插入点后面的所有元素都将后移一位,其效果如图2.7(a)所示。

1.    元素的删除操作

7386行的RemoveAt(int index)方法用于删除指定索引的元素,删除指定元素后,删除点后的所有元素将向前移动一位其效果如图2.7(b)所示。

下面对ArrayList类进行测试。

【例2-1ArrayList的使用

新建一个控制台应用程序,并在项目中把上面的ArrayList.cs文件做为一个【现有项】添加进去。在代码窗体前面使用如下语句加入LinearList命名空间:

using LinearList;

并在Main方法中输入如下代码:

1  static void Main(string[] args)

2  {

3      ArrayList arr = new ArrayList();

4      Console.WriteLine("arr现在的容量为:" + arr.Capacity + "  长度为:" + arr.Count);

5      arr.Add(1); //添加一个元素

6      Console.WriteLine("arr现在的容量为:" + arr.Capacity + "  长度为:" + arr.Count);

7      for (int i = 2; i <= 5; i++)

8      {   //添加4个元素,完成后元素总数达到5

9          arr.Add(i);

10     }

11     Console.WriteLine("arr现在的容量为:" + arr.Capacity + "  长度为:" + arr.Count);

12     for (int i = 6; i <= 9; i++)

13     {   //添加4个元素,完成后元素总数达到9

14         arr.Add(i);

15     }

16     Console.WriteLine("arr现在的容量为:" + arr.Capacity + "  长度为:" + arr.Count);

17     for (int i = 0; i < arr.Count; i++) //打印所有元素

18     {

19         Console.Write(i + "  ");

20     }

21     //删除两个元素

22     arr.RemoveAt(arr.Count - 1);

23     arr.RemoveAt(arr.Count - 1);

24     Console.WriteLine(); //换行

25     for (int i = 0; i < arr.Count; i++) //打印所有元素

26     {

27         Console.Write(i + "  ");

28     }

29     Console.WriteLine(); //换行

30     Console.WriteLine("arr现在的容量为:" + arr.Capacity + "  长度为:" + arr.Count);

31     arr.TrimToSize(); //载减多余空间

32     Console.WriteLine("arr现在的容量为:" + arr.Capacity + "  长度为:" + arr.Count);

33 }

运行结果:如图2.8所示。

由运行结果可以得知,数组对象arr的容量随着元素的不断增加,从04816不断改变,在删除两个元素之后,容量还保持在16不变,在通过调用TrimToSize()裁减空间后,容量最终变为7

2.2.4 类型安全

数组和ArrayList的本质区别在于前者是类型安全的,而后者不是类型安全的。ArrayList为了兼容所有类型的对象,使用了object数组,这给使用带来了一些的麻烦。如下例所示:

【例2-2】数组和ArrayList的对比

本例使用了C#类库中的ArrayList而不是前面自定义的ArrayList,它存在于System.Collections命名空间中。新建一个控制台应用程序,引入System.Collections命名空间,并在Main()方法中输入如下代码:

1  static void Main(string[] args)

2  {

3      int[] arr = new int[2];

4      arr[0] = 5;

5      arr[1] = 6;

6      int result = arr[0] * arr[1];

7      Console.WriteLine(result);

8      ArrayList arrL = new ArrayList();

9      arrL.Add(5);

10     arrL.Add(6);

11     result = (int)arrL[0] * (int)arrL[1];

12     Console.WriteLine(result);

13 }

运行结果:

30

30

本例使用数组和ArrayList分别做了相同的事情,但使用方法却大相径庭。首先数组在创建时就已经确定只接收int类型数据,并且它的长度是固定的。而ArrayList则可以接收任意object类型,而事实上,C#中的所有类均是<span

分享到:
评论

相关推荐

    你必须知道的C# ArrayList

    C# ArrayList是一个重要的数据结构,它是.NET框架早期版本中用于动态数组存储的类。这个类在System.Collections命名空间中,提供了灵活的大小调整和数据管理功能。ArrayList在C#编程中扮演了重要的角色,尤其在处理...

    C# Array和ArrayList,List区别

    ### C# 中 Array、ArrayList 和 List 的区别 在C#编程语言中,处理集合数据时,程序员经常需要根据实际需求选择合适的集合类型。本文将详细解释C#中Array、ArrayList和List之间的区别,并通过示例代码帮助理解这些...

    精通C#--第六版

    8. **集合和泛型集合**:了解ArrayList、LinkedList、Dictionary等常用集合类,以及泛型集合的使用。 9. **异常处理**:学习如何使用try-catch块进行错误处理,确保程序的健壮性。 10. **.NET Framework**:理解...

    VS2010轻松学习C#-从零到深入-天轰穿.NET4趣味编程视频教程_第22讲:深入数组

    9. **动态数组**:C# 2.0引入的`ArrayList`和`List&lt;T&gt;`类允许创建动态大小的数组,它们的大小可以根据需要自动调整。 ```csharp ArrayList myList = new ArrayList(); myList.Add(10); myList.Add(20); List...

    C#数组与Arraylist

    在编程领域,尤其是在C#语言中,数组和ArrayList是两种常用的数据存储结构。它们各自有其特点和适用场景,理解并熟练运用它们是提升编程能力的关键。本文将深入探讨数组和ArrayList,帮助你掌握这两种数据结构的核心...

    C#ArrayList的详细用法

    C# ArrayList 的详细用法 C# ArrayList 是一个特殊的数组,通过添加和删除元素,可以动态改变数组的长度。ArrayList 提供了多种方法来操作数组元素,包括添加、插入、删除、排序等。 一、优点 1. 支持自动改变...

    C#中数组与arraylist

    在C#编程语言中,数组和ArrayList是两种不同的数据结构,它们各自有着特定的用途和特点。本篇文章将深入探讨这两种数据结构,以及它们在实际编程中的应用与区别。 首先,数组是C#中最基本的数据结构之一,它是一种...

    C#ArrayList用法

    ### C# 中 ArrayList 的使用详解 #### 一、概述 在C#中,`ArrayList`是一种非常实用的数据结构,它可以被视为动态数组的一种形式。相比于普通的数组,`ArrayList`提供了更加灵活的功能,比如动态地增加和减少元素,...

    C# ArrayList用法大全

    C# ArrayList用法大全 C# 的 ArrayList 是一个特殊的数组,通过添加和删除元素,可以动态改变数组的长度。下面是 ArrayList 的详细用法大全: 一、优点 1. 支持自动改变大小的功能:ArrayList 可以根据需要自动...

    C# ArrayList教程

    C# ArrayList教程 详细介绍了ArrayList的使用过程,对于学习C#的人很有帮助!

    ArrayList转化为DataTable

    在.NET框架中,ArrayList和DataTable是两种常用的集合类,它们分别代表了两种不同的数据存储方式。ArrayList是一个基于对象数组的动态大小的列表,而DataTable则是一个内存中的表格数据结构,通常用于存储和操作关系...

    c#重写ArrayList源代码

    在C#编程中,ArrayList是System.Collections命名空间中的一个类,它是.NET框架早期版本中用于存储动态大小对象数组的主要容器。然而,随着.NET Framework的发展,更高效、类型安全的List类应运而生。尽管如此,了解...

    C#-.Net常见面试试题 备答案

    - .NET框架提供的各种集合类,如ArrayList、LinkedList、HashSet、Dictionary等。 - 泛型集合与非泛型集合的区别。 - 对象池的设计和使用。 8. **文件与IO操作** - 文件读写,如File类和StreamReader/...

    有关于C#的程序(ArrayList类,动态添加,删除的)

    在C#编程语言中,ArrayList类是System.Collections命名空间下的一个重要的数据结构,它提供了动态数组的功能,允许我们在运行时改变数组的大小。ArrayList类基于对象的数组,可以存储任何类型的对象,这得益于C#的多...

    C#--微软.NET的第一语言,本书着重介绍语言本身

    13. **异构集合与泛型集合**:Array、ArrayList和LinkedList等传统集合已被泛型集合如List和Dictionary, TValue&gt;所取代,提供了更好的类型安全性和性能。 通过学习以上知识点,你可以逐步掌握C#的基础,并为进一步...

    public-ArrayList-GetFiles.rar_网络编程_C#_

    标题中的"public-ArrayList-GetFiles.rar_网络编程_C#"暗示了这个压缩包可能包含一个C#编程示例,用于在网络编程中获取服务器上的文件。ArrayList是.NET框架早期版本中常用的一种动态数组类,用于存储可变大小的对象...

    C#中的ArrayList导图

    ArrayList。  首先,它不是静态的,编译时每一维度的元素个数不用指定,系统默认元素个数为16,当元素增多并即将大于16时,它会增倍扩容到32,依次规律增长,变小时,相反处理。  其次,元素类型是弱类型,object...

    C#--微软.NET的第一语言+中文版电子书

    3. **集合与泛型**:探讨ArrayList、List、Dictionary,TValue&gt;等数据结构的使用,以及泛型容器的应用。 4. **文件与流**:介绍如何进行文件读写操作,以及网络流、内存流的使用。 5. **Windows Forms与WPF**:讲解...

    c# 数组与集合(ArrayList)游戏开发高级使用举例

    C#中的数组和ArrayList都是常见的数据存储方式,但它们有着不同的特性和应用场景。本篇主要探讨C#数组和ArrayList在游戏开发中的高级使用技巧。 首先,数组是C#中最基础的数据结构之一。它是一个存储相同类型元素的...

    最全面的C#-DataGridView控件介绍

    - DataSource:用于设置数据源,可以是DataTable、DataSet、ArrayList或其他数据结构。 - Columns:此属性提供对列的集合访问,允许添加、删除和修改列。 - Rows:提供了对行的集合访问,用于添加、删除和修改行...

Global site tag (gtag.js) - Google Analytics