C# 动态数组(ArrayList)

C# 集合 C# 集合

ArrayList 是 C# 中提供的一种动态数组类,位于命名空间 System.Collections 中。

动态数组(ArrayList)与普通数组不同,它的大小可以动态调整,无需预先定义固定长度。

动态数组(ArrayList)代表了可被单独索引的对象的有序集合,它也允许在列表中进行动态内存分配、增加、搜索、排序各项。

ArrayList 类适用于需要频繁调整大小的数组操作,但由于其非泛型特性,在现代 C# 开发中逐渐被 List<T> 替代。

基本结构

public class ArrayList : ICollection, IEnumerable, IList, ICloneable

实现接口:

  • 实现接口
    • IList:支持按索引访问元素。
    • ICollection:支持集合基本操作,如添加、删除和计数。
    • IEnumerable:支持通过枚举器遍历元素。
    • ICloneable:支持克隆 ArrayList

特点

动态扩展

  • ArrayList 的容量可以根据需要自动调整,不需要指定固定大小。
  • 当添加的元素超过当前容量时,ArrayList 会自动增加容量(通常是原容量的两倍)。

非泛型集合

  • ArrayList 是非泛型集合,所有元素被存储为 object 类型。这意味着它可以存储任意类型的对象,但需要注意装箱(boxing)和拆箱(unboxing)的性能影响。

无序操作

  • 虽然元素存储顺序与添加顺序一致,但它并不提供内置排序功能。

线程安全

  • 默认不是线程安全的。如果需要线程安全的 ArrayList,可以使用 ArrayList.Synchronized 方法生成一个线程安全的版本。

ArrayList 类的方法和属性

下表列出了 ArrayList 类的一些常用的 属性

属性名称类型描述
Countint获取 ArrayList 中包含的元素数量。
Capacityint获取或设置 ArrayList 的容量(存储空间)。
IsFixedSizebool指示 ArrayList 是否具有固定大小。
IsReadOnlybool指示 ArrayList 是否为只读。
IsSynchronizedbool指示 ArrayList 是否线程安全。
SyncRootobject获取可用于同步访问的对象。

下表列出了 ArrayList 类的一些常用的 方法

方法名称返回类型描述
添加与插入
Add(object value)int将对象添加到 ArrayList 的末尾,返回新元素的索引。
AddRange(ICollection c)void将指定集合的所有元素添加到 ArrayList 的末尾。
Insert(int index, object value)void在指定索引处插入对象。
InsertRange(int index, ICollection c)void在指定索引处插入指定集合的所有元素。
删除
Remove(object value)void移除首次出现的指定对象。
RemoveAt(int index)void移除指定索引处的元素。
RemoveRange(int index, int count)void移除从指定索引开始的指定数量的元素。
Clear()void移除所有元素。
访问与查询
Contains(object item)bool判断 ArrayList 是否包含指定对象。
IndexOf(object value)int获取指定对象首次出现的索引。
LastIndexOf(object value)int获取指定对象最后一次出现的索引。
排序与复制
Sort()void按照默认顺序排序 ArrayList 中的元素。
Sort(IComparer comparer)void按照自定义比较器排序。
Reverse()void反转 ArrayList 中元素的顺序。
CopyTo(Array array)voidArrayList 的元素复制到指定数组中。
其他
GetRange(int index, int count)ArrayList获取从指定索引开始的指定数量的元素子集。
ToArray()object[]ArrayList 中的元素复制到数组中。
TrimToSize()void将容量调整为实际元素数量以节省内存。

实例

下面的实例演示了动态数组(ArrayList)的概念:

实例

using System;
using System.Collections;

namespace CollectionApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            // 创建动态数组并初始化
            ArrayList numbers = InitializeArrayList();

            // 显示数组的容量和元素个数
            DisplayArrayListInfo(numbers);

            // 显示数组内容
            Console.Write("Original Content: ");
            DisplayArrayListContent(numbers);

            // 对数组内容排序
            numbers.Sort();

            // 显示排序后的内容
            Console.Write("Sorted Content: ");
            DisplayArrayListContent(numbers);

            Console.ReadKey(); // 等待用户按键退出
        }

        /// <summary>
        /// 初始化并填充 ArrayList
        /// </summary>
        /// <returns>包含初始数据的 ArrayList</returns>
        static ArrayList InitializeArrayList()
        {
            ArrayList al = new ArrayList();
            Console.WriteLine("Adding numbers to the ArrayList:");
           
            // 添加初始元素
            int[] initialNumbers = { 45, 78, 33, 56, 12, 23, 9 };
            foreach (int num in initialNumbers)
            {
                al.Add(num);
                Console.WriteLine($"Added: {num}");
            }

            return al;
        }

        /// <summary>
        /// 显示 ArrayList 的容量和元素个数
        /// </summary>
        /// <param name="al">ArrayList 对象</param>
        static void DisplayArrayListInfo(ArrayList al)
        {
            Console.WriteLine($"\nCapacity: {al.Capacity}"); // 当前容量
            Console.WriteLine($"Count: {al.Count}");         // 当前元素个数
        }

        /// <summary>
        /// 显示 ArrayList 的内容
        /// </summary>
        /// <param name="al">ArrayList 对象</param>
        static void DisplayArrayListContent(ArrayList al)
        {
            foreach (int num in al)
            {
                Console.Write(num + " ");
            }
            Console.WriteLine(); // 换行
        }
    }
}

当上面的代码被编译和执行时,它会产生下列结果:

Adding numbers to the ArrayList:
Added: 45
Added: 78
Added: 33
Added: 56
Added: 12
Added: 23
Added: 9

Capacity: 16
Count: 7
Original Content: 45 78 33 56 12 23 9 
Sorted Content: 9 12 23 33 45 56 78 

与泛型集合 List<T> 的对比

特性ArrayListList<T>
类型安全否(存储 object 类型)是(泛型,强类型约束)
装箱与拆箱是(值类型需要)
性能较低较高
泛型支持
使用场景遗留代码或简单场景现代开发中优先选择

注意事项

避免频繁装箱和拆箱

  • 如果数据主要是值类型,建议使用 List<T> 来避免性能开销。

慎用混合类型数据

  • 尽量不要混合存储不同类型的对象,以降低运行时错误的风险。

替代方案

  • 在现代 C# 开发中,推荐使用泛型集合(如 List<T>Dictionary<TKey, TValue>)以提高代码的安全性和效率。

C# 集合 C# 集合