C# 动态数组(ArrayList)
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 类的一些常用的 属性:
属性名称 | 类型 | 描述 |
---|---|---|
Count | int | 获取 ArrayList 中包含的元素数量。 |
Capacity | int | 获取或设置 ArrayList 的容量(存储空间)。 |
IsFixedSize | bool | 指示 ArrayList 是否具有固定大小。 |
IsReadOnly | bool | 指示 ArrayList 是否为只读。 |
IsSynchronized | bool | 指示 ArrayList 是否线程安全。 |
SyncRoot | object | 获取可用于同步访问的对象。 |
下表列出了 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) | void | 将 ArrayList 的元素复制到指定数组中。 |
其他 | ||
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(); // 换行
}
}
}
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>
的对比
特性 | ArrayList | List<T> |
---|---|---|
类型安全 | 否(存储 object 类型) | 是(泛型,强类型约束) |
装箱与拆箱 | 是(值类型需要) | 否 |
性能 | 较低 | 较高 |
泛型支持 | 无 | 有 |
使用场景 | 遗留代码或简单场景 | 现代开发中优先选择 |
注意事项
避免频繁装箱和拆箱:
- 如果数据主要是值类型,建议使用
List<T>
来避免性能开销。
慎用混合类型数据:
- 尽量不要混合存储不同类型的对象,以降低运行时错误的风险。
替代方案:
- 在现代 C# 开发中,推荐使用泛型集合(如
List<T>
、Dictionary<TKey, TValue>
)以提高代码的安全性和效率。
tmelody
tme***yleoyoung@163.com
ArrayList 存储不同类型时的排序:
输出结果为:
tmelody
tme***yleoyoung@163.com
黑人的乔丹鞋
hei***2455780149@163.com
这是 ArrayList 中 Add 方法的源码:
通过上面的源码可以看出,它会自动扩大数组的容量。
这是索引器的源代码:
可以看出,它并不会扩容。
结论:添加元素只能用Add,不能用索引器。黑人的乔丹鞋
hei***2455780149@163.com