C# 传递数组给函数(手把手讲解)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...点击查看项目介绍 ;
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;

截止目前, 星球 内专栏累计输出 82w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2900+ 小伙伴加入学习 ,欢迎点击围观

在 C# 编程中,函数(或方法)是代码复用的核心工具。当我们需要对一组数据进行处理时,数组往往是最直观的容器。然而,如何将数组传递给函数,并确保其行为符合预期,是许多开发者在学习过程中会遇到的挑战。本文将通过循序渐进的讲解,结合生动的比喻和实际代码案例,帮助读者掌握这一关键技能。


3. 数组传递的三种方式

在 C# 中,数组传递主要涉及以下三种核心场景:直接传递数组引用通过 params 关键字传递可变参数,以及返回数组作为函数结果

3.1 直接传递数组引用

数组是 C# 中的引用类型(Reference Type),这意味着当我们将数组传递给函数时,传递的实际上是数组的内存地址引用,而非数组本身的拷贝。这一特性类似于将一个“快递单”交给快递员,快递员通过地址找到包裹并修改其内容。例如:

void ModifyArray(int[] arr)  
{  
    arr[0] = 100; // 直接修改原数组的第一个元素  
}  

int[] numbers = { 1, 2, 3 };  
ModifyArray(numbers);  
Console.WriteLine(numbers[0]); // 输出 100  

关键点:函数内部对数组元素的修改会直接影响原数组。因此,传递数组时需格外注意副作用

3.2 使用 params 关键字传递可变参数

当函数需要接收不确定数量的参数时,可以使用 params 关键字。这会将参数自动封装为一个数组。例如:

void PrintNumbers(params int[] nums)  
{  
    foreach (var num in nums)  
        Console.Write(num + " ");  
}  

// 调用时无需显式创建数组  
PrintNumbers(1, 2, 3, 4); // 输出 1 2 3 4  

比喻params 好比一个“收集器”,它会将零散的参数“打包”成一个数组,方便统一处理。

3.3 返回数组作为函数结果

函数也可以返回一个数组,这在数据生成或转换场景中非常有用。例如:

int[] GenerateFibonacci(int count)  
{  
    int[] result = new int[count];  
    result[0] = 0;  
    if (count > 1)  
        result[1] = 1;  
    for (int i = 2; i < count; i++)  
        result[i] = result[i - 1] + result[i - 2];  
    return result;  
}  

int[] fib = GenerateFibonacci(5); // [0, 1, 1, 2, 3]  

4. 数组传递的注意事项

4.1 引用传递的陷阱

由于数组是引用类型,若函数内部重新分配了数组的内存地址(例如 arr = new int[5]),则原数组不会受到影响。例如:

void ResetArray(int[] arr)  
{  
    arr = new int[5]; // 此时原数组未被修改!  
    arr[0] = 5;  
}  

int[] data = { 1, 2, 3 };  
ResetArray(data);  
Console.WriteLine(data[0]); // 仍输出 1  

解决方案:若需修改原数组的引用,应通过 outref 关键字显式传递:

void ResetArray(ref int[] arr)  
{  
    arr = new int[5];  
    arr[0] = 5;  
}  

ResetArray(ref data); // 现在 data 是新数组  

4.2 多维数组的传递

C# 中的多维数组(如 int[,])和交错数组(int[][])传递方式略有不同。例如:

// 传递多维数组  
void ProcessMatrix(int[,] matrix)  
{  
    matrix[0, 0] = 10; // 修改原数组  
}  

// 传递交错数组(数组的数组)  
void ProcessList(int[][] list)  
{  
    list[0][0] = 20; // 修改原数组  
}  

4.3 性能优化与深拷贝

若需避免函数修改原数组,可以通过深拷贝创建独立的副本:

int[] CopyArray(int[] source)  
{  
    int[] copy = new int[source.Length];  
    Array.Copy(source, copy, source.Length);  
    return copy;  
}  

5. 实际案例:排序算法与数组传递

5.1 冒泡排序函数

以下案例展示如何通过函数实现冒泡排序,并传递数组进行原地修改:

void BubbleSort(int[] arr)  
{  
    int n = arr.Length;  
    for (int i = 0; i < n - 1; i++)  
    {  
        for (int j = 0; j < n - i - 1; j++)  
        {  
            if (arr[j] > arr[j + 1])  
            {  
                // 交换元素  
                int temp = arr[j];  
                arr[j] = arr[j + 1];  
                arr[j + 1] = temp;  
            }  
        }  
    }  
}  

int[] numbers = { 64, 34, 25, 12, 22, 11, 90 };  
BubbleSort(numbers); // 原数组被排序  

5.2 使用 params 实现动态参数的平均值计算

double CalculateAverage(params double[] values)  
{  
    if (values.Length == 0) return 0;  
    return values.Sum() / values.Length;  
}  

double avg = CalculateAverage(10.5, 20.3, 30.7); // 输出 20.5  

6. 进阶技巧与常见问题

6.1 params 的限制

  • params 必须是方法参数列表中的最后一个参数。
  • 不能与 outref 同时使用。

6.2 泛型数组的传递

通过泛型函数,可以传递任意类型的数组:

void PrintElements<T>(T[] items)  
{  
    foreach (var item in items)  
        Console.WriteLine(item);  
}  

PrintElements(new string[] { "Apple", "Banana" });  
PrintElements(new int[] { 1, 2, 3 });  

6.3 通过 Array.Resize 动态调整数组

int[] data = { 1, 2, 3 };  
Array.Resize(ref data, 5); // 扩展为长度5的数组,新增元素默认为0  

7. 结论

掌握“C# 传递数组给函数”的核心逻辑,是开发者高效利用数组和函数的关键。通过理解引用传递的特性、灵活使用 paramsref 等关键字,以及结合实际案例进行实践,开发者可以编写出更清晰、可维护的代码。无论是基础的数据处理,还是复杂算法的实现,数组与函数的结合都能为程序设计提供强大的灵活性。

希望本文能帮助读者在 C# 开发的道路上迈出坚实的一步,并在未来遇到相关问题时,能够游刃有余地运用这些知识。

最新发布