目 录CONTENT

文章目录

CSharp(十七) Array数组定义

CSharp(十七) Array数组定义

一、Array 类概述

Array 是 C# 中所有数组的基类,位于 System 命名空间下。它提供了创建、操作、搜索和排序数组的静态方法和实例方法。在 C# 中,数组是引用类型,继承自 Array 类。

二、数组声明与创建

2.1 一维数组

// 声明并初始化
int[] numbers = new int[5];
int[] numbers2 = new int[] { 1, 2, 3, 4, 5 };
int[] numbers3 = { 1, 2, 3, 4, 5 };  // 简写形式

// 使用 Array 类静态方法创建
Array array = Array.CreateInstance(typeof(int), 5);

2.2 多维数组

// 二维数组
int[,] matrix = new int[3, 4];
int[,] matrix2 = { { 1, 2, 3 }, { 4, 5, 6 } };

// 三维数组
int[,,] cube = new int[2, 3, 4];

2.3 交错数组(数组的数组)

// 交错数组
int[][] jagged = new int[3][];
jagged[0] = new int[] { 1, 2 };
jagged[1] = new int[] { 3, 4, 5 };
jagged[2] = new int[] { 6 };

三、Array 类常用属性

属性 说明 示例
Length 获取数组所有维度元素的总数 int len = arr.Length;
LongLength 获取 64 位长度的数组元素总数 long len = arr.LongLength;
Rank 获取数组的维数 int rank = arr.Rank;
IsFixedSize 数组是否具有固定大小(始终为 true) bool fixed = arr.IsFixedSize;
IsReadOnly 数组是否只读(始终为 false) bool ro = arr.IsReadOnly;
int[] arr = { 1, 2, 3, 4, 5 };
Console.WriteLine(arr.Length);      // 输出: 5
Console.WriteLine(arr.Rank);        // 输出: 1 (一维数组)

int[,] matrix = new int[3, 4];
Console.WriteLine(matrix.Length);   // 输出: 12 (3*4)
Console.WriteLine(matrix.Rank);     // 输出: 2 (二维数组)

四、Array 类常用方法

4.1 数组遍历与访问

int[] arr = { 10, 20, 30, 40, 50 };

// 使用索引访问
Console.WriteLine(arr[0]);  // 10

// 使用 GetValue / SetValue(适用于运行时类型不确定的情况)
Array array = arr;
Console.WriteLine(array.GetValue(0));  // 10
array.SetValue(100, 0);  // 将索引0的值设为100

4.2 数组排序

int[] arr = { 5, 2, 8, 1, 9 };

// 升序排序
Array.Sort(arr);
// 结果: { 1, 2, 5, 8, 9 }

// 降序排序
Array.Sort(arr);
Array.Reverse(arr);
// 结果: { 9, 8, 5, 2, 1 }

// 部分排序
int[] arr2 = { 5, 2, 8, 1, 9, 3 };
Array.Sort(arr2, 1, 3);  // 从索引1开始,排序3个元素
// 结果: { 5, 1, 2, 8, 9, 3 }

// 自定义排序(字符串按长度排序)
string[] names = { "Alice", "Bob", "Christina", "Dave" };
Array.Sort(names, (a, b) => a.Length.CompareTo(b.Length));

4.3 数组搜索

int[] arr = { 10, 20, 30, 40, 50 };

// 二分查找(要求数组已排序)
Array.Sort(arr);
int index = Array.BinarySearch(arr, 30);  // 返回: 2
int notFound = Array.BinarySearch(arr, 25);  // 返回负数,表示不存在

// 线性查找
int idx = Array.IndexOf(arr, 30);  // 返回: 2
int lastIdx = Array.LastIndexOf(arr, 30);  // 返回: 2

// 查找满足条件的元素
int[] numbers = { 1, 2, 3, 4, 5, 6 };
int firstEven = Array.Find(numbers, x => x % 2 == 0);  // 返回: 2
int lastEven = Array.FindLast(numbers, x => x % 2 == 0);  // 返回: 6
int[] allEven = Array.FindAll(numbers, x => x % 2 == 0);  // 返回: { 2, 4, 6 }
int evenIndex = Array.FindIndex(numbers, x => x % 2 == 0);  // 返回: 1
bool exists = Array.Exists(numbers, x => x > 5);  // 返回: true

4.4 数组复制

int[] arr = { 1, 2, 3, 4, 5 };

// 浅拷贝(Clone)
int[] clone = (int[])arr.Clone();

// 使用 CopyTo
int[] target = new int[5];
arr.CopyTo(target, 0);

// 使用 Array.Copy
int[] dest = new int[5];
Array.Copy(arr, dest, arr.Length);

// 指定范围复制
int[] dest2 = new int[3];
Array.Copy(arr, 1, dest2, 0, 3);  // 从arr[1]开始复制3个元素到dest2
// 结果: dest2 = { 2, 3, 4 }

// 使用 Array.ConstrainedCopy(保证原子性,失败时目标数组不受影响)
Array.ConstrainedCopy(arr, 0, dest, 0, arr.Length);

4.5 数组清空与填充

int[] arr = { 1, 2, 3, 4, 5 };

// 清空数组(设为默认值)
Array.Clear(arr, 0, arr.Length);
// 结果: { 0, 0, 0, 0, 0 }

// 部分清空
int[] arr2 = { 1, 2, 3, 4, 5 };
Array.Clear(arr2, 1, 3);
// 结果: { 1, 0, 0, 0, 5 }

// 填充数组
// 注意:Array 类没有 Fill 方法,但可以使用扩展或循环
// .NET Core 2.0+ 支持 Array.Fill
Array.Fill(arr, 9);  // 全部填充为9
Array.Fill(arr, 7, 1, 3);  // 从索引1开始,填充3个元素为7

4.6 数组反转

int[] arr = { 1, 2, 3, 4, 5 };

// 全部反转
Array.Reverse(arr);
// 结果: { 5, 4, 3, 2, 1 }

// 部分反转
int[] arr2 = { 1, 2, 3, 4, 5 };
Array.Reverse(arr2, 1, 3);
// 结果: { 1, 4, 3, 2, 5 }

4.7 数组遍历(ForEach)

string[] names = { "Alice", "Bob", "Charlie" };

// 使用 Array.ForEach
Array.ForEach(names, name => Console.WriteLine(name));

// 使用 foreach 语句(更常用)
foreach (var name in names)
{
    Console.WriteLine(name);
}

五、多维数组操作

5.1 获取和设置多维数组元素

int[,] matrix = { { 1, 2, 3 }, { 4, 5, 6 } };

// 获取维度长度
int rows = matrix.GetLength(0);  // 2 (第一维长度)
int cols = matrix.GetLength(1);  // 3 (第二维长度)

// 获取各维度下限(通常为0)
int lowerBound0 = matrix.GetLowerBound(0);  // 0
int lowerBound1 = matrix.GetUpperBound(1);  // 2

// 使用 GetValue / SetValue(参数为索引数组)
Array arr = matrix;
Console.WriteLine(arr.GetValue(0, 1));  // 2
arr.SetValue(100, 0, 1);  // 将 matrix[0,1] 设为 100

5.2 遍历多维数组

int[,] matrix = { { 1, 2, 3 }, { 4, 5, 6 } };

// 使用嵌套循环
for (int i = 0; i < matrix.GetLength(0); i++)
{
    for (int j = 0; j < matrix.GetLength(1); j++)
    {
        Console.Write($"{matrix[i, j]} ");
    }
    Console.WriteLine();
}

// 使用 foreach(按行优先顺序遍历)
foreach (int val in matrix)
{
    Console.Write($"{val} ");
}

六、数组转换

// 数组转 List
int[] arr = { 1, 2, 3 };
List<int> list = arr.ToList();

// 数组转 IEnumerable
IEnumerable<int> enumerable = arr.AsEnumerable();

// 类型转换(Cast)
object[] objArr = { 1, 2, 3 };
int[] intArr = objArr.Cast<int>().ToArray();

// 使用 OfType 过滤特定类型
object[] mixed = { 1, "hello", 2, "world", 3 };
int[] ints = mixed.OfType<int>().ToArray();  // { 1, 2, 3 }

七、数组切片与范围(C# 8.0+)

int[] arr = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

// 使用范围运算符
int[] slice1 = arr[2..5];    // { 2, 3, 4 }
int[] slice2 = arr[..5];     // { 0, 1, 2, 3, 4 }
int[] slice3 = arr[5..];      // { 5, 6, 7, 8, 9 }
int[] slice4 = arr[^3..];     // { 7, 8, 9 } (最后3个)
int[] slice5 = arr[1..^1];    // { 1, 2, 3, 4, 5, 6, 7, 8 } (去掉首尾)

// 使用 Span(高效内存切片,不复制数据)
Span<int> span = arr.AsSpan(2, 5);  // 引用 arr[2..7]

八、数组与 LINQ

int[] numbers = { 5, 2, 8, 1, 9, 3 };

// 排序
var sorted = numbers.OrderBy(n => n).ToArray();

// 过滤
var evens = numbers.Where(n => n % 2 == 0).ToArray();

// 投影
var squares = numbers.Select(n => n * n).ToArray();

// 聚合
int sum = numbers.Sum();
int max = numbers.Max();
int min = numbers.Min();
double avg = numbers.Average();

// 分组
var groups = numbers.GroupBy(n => n % 2).ToArray();

九、性能优化技巧

9.1 使用 Span 和 Memory

int[] arr = { 1, 2, 3, 4, 5 };

// Span - 栈上分配的内存切片(高性能,无堆分配)
Span<int> span = arr.AsSpan(1, 3);
span[0] = 100;  // 修改会影响原数组

// ReadOnlySpan - 只读切片
ReadOnlySpan<int> roSpan = arr.AsSpan();

// Memory - 可用于异步操作的内存切片
Memory<int> memory = arr.AsMemory(1, 3);

9.2 数组池(ArrayPool)

// 使用 ArrayPool 减少 GC 压力
int[] rented = ArrayPool<int>.Shared.Rent(100);
try
{
    // 使用 rented 数组(长度可能大于100)
    for (int i = 0; i < 100; i++)
    {
        rented[i] = i;
    }
}
finally
{
    // 必须归还到池中
    ArrayPool<int>.Shared.Return(rented);
}

十、完整示例代码

using System;
using System.Linq;

class Program
{
    static void Main()
    {
        // 1. 创建数组
        int[] numbers = { 5, 2, 8, 1, 9, 3 };
        Console.WriteLine($"原数组: {string.Join(", ", numbers)}");

        // 2. 排序
        Array.Sort(numbers);
        Console.WriteLine($"排序后: {string.Join(", ", numbers)}");

        // 3. 反转
        Array.Reverse(numbers);
        Console.WriteLine($"反转后: {string.Join(", ", numbers)}");

        // 4. 查找
        int index = Array.IndexOf(numbers, 5);
        Console.WriteLine($"5 的索引: {index}");

        // 5. 二分查找
        Array.Sort(numbers);
        int found = Array.BinarySearch(numbers, 5);
        Console.WriteLine($"二分查找 5: {found}");

        // 6. 复制
        int[] copy = new int[numbers.Length];
        Array.Copy(numbers, copy, numbers.Length);
        Console.WriteLine($"复制: {string.Join(", ", copy)}");

        // 7. 使用 LINQ
        var evens = numbers.Where(n => n % 2 == 0).ToArray();
        Console.WriteLine($"偶数: {string.Join(", ", evens)}");

        // 8. 多维数组
        int[,] matrix = { { 1, 2, 3 }, { 4, 5, 6 } };
        Console.WriteLine($"矩阵行数: {matrix.GetLength(0)}, 列数: {matrix.GetLength(1)}");

        // 9. 遍历多维数组
        for (int i = 0; i < matrix.GetLength(0); i++)
        {
            for (int j = 0; j < matrix.GetLength(1); j++)
            {
                Console.Write($"{matrix[i, j]} ");
            }
            Console.WriteLine();
        }
    }
}

十一、注意事项

  1. 数组越界:访问 arr[arr.Length] 会抛出 IndexOutOfRangeException
  2. 数组是固定大小:创建后不能改变大小,需要调整大小请使用 Array.ResizeList<T>
  3. 引用类型数组:数组元素是引用类型时,存储的是引用而非对象本身
  4. 协变数组:C# 支持数组协变,但可能导致运行时异常,建议使用泛型集合
// 数组协变(需谨慎使用)
object[] objArr = new string[3];
objArr[0] = "hello";  // 正常
// objArr[1] = 123;   // 运行时抛出 ArrayTypeMismatchException
0
博主关闭了当前页面的评论