C# Array类型深度剖析
Array是所有一维和多维数组的基类,提供统一的集合操作接口。无论数组声明方式如何,所有数组实例都共享相同的核心方法集。
当声明数组时,CLR会生成继承自Array的派生类型,该类型自动实现泛型集合接口如IList。数组元素在内存中连续存储,确保高效索引访问,但创建后长度不可变。
数组支持值类型和引用类型元素存储。值类型直接内联存储,而引用类型仅存储对象指针。以下示例展示内存布局差异:
var textBuilders = new StringBuilder[4];
textBuilders[0] = new StringBuilder("text1");
textBuilders[1] = new StringBuilder("text2");
var values = new double[3];
values[0] = 12.34;
values[1] = 56.78;
数组本身是引用类型,赋值操作仅复制引用。深度比较需使用结构化比较器:
object[] set1 = { "text", 100, false };
object[] set2 = { "text", 100, false };
Console.WriteLine(set1 == set2); // 输出False
var comparer = StructuralComparisons.StructuralEqualityComparer;
Console.WriteLine(comparer.Equals(set1, set2)); // 输出True
Clone方法创建浅拷贝副本:
var cloned = (StringBuilder[])textBuilders.Clone();
动态创建与访问
除字面量声明外,可通过反射动态创建数组:
Array dynArray = Array.CreateInstance(typeof(string), 2);
dynArray.SetValue("Hello", 0);
string val = (string)dynArray.GetValue(0);
多维数组访问示例:
void PrintFirstElement(Array arr)
{
int[] indices = new int[arr.Rank];
Console.WriteLine(arr.GetValue(indices));
}
var matrix = new int[,] { { 10, 20 }, { 30, 40 } };
PrintFirstElement(matrix); // 输出10
遍历与维度
数组遍历方式:
int[] data = { 10, 20, 30 };
Array.ForEach(data, Console.WriteLine); // 输出10\n20\n30
维度操作方法:
int[,,] cube = new int[2,3,4];
Console.WriteLine(cube.GetLength(1)); // 输出3
Console.WriteLine(cube.Rank); // 输出3
搜索与排序
二分查找要求数组有序:
int[] sorted = { 5, 10, 15 };
int pos = Array.BinarySearch(sorted, 10); // 返回1
条件查找示例:
string[] items = { "apple", "banana", "cherry" };
string result = Array.Find(items, s => s.StartsWith("b")); // 返回banana
双数组协同排序:
int[] ids = { 3, 1, 2 };
string[] names = { "C", "A", "B" };
Array.Sort(ids, names); // names变为["A","B","C"]
复制与转换
数组复制方法对比:
int[] source = { 1, 2, 3 };
int[] target = new int[3];
// 浅拷贝
Array.Copy(source, target, source.Length);
类型转换示例:
float[] floats = { 1.2f, 3.4f };
int[] integers = Array.ConvertAll(floats, f => (int)f); // 得到[1,3]
调整数组大小会创建新数组:
Array.Resize(ref source, 5); // 新数组长度为5