当前位置: 首页 > news >正文

7.C# —— 方法返回值、值传递、ref/out/in/params

在 C# 开发中,方法是封装代码逻辑的核心单元,而方法的返回值参数传递机制是必须掌握的基础核心。本文通过通俗易懂的案例,系统讲解 C# 方法返回值、值传递、引用传递(ref/out/in)以及 params 可变参数

一、方法返回值

方法的返回值决定了方法执行后能向外输出什么数据,C# 中通过返回值类型定义,分为无返回值有返回值两种,返回值可以是基本类型、自定义对象等。

1. 无返回值(void)

使用void关键字修饰,方法执行后不向外传递数据,只能在方法内部执行逻辑(如打印、运算),无法将结果拿到方法外部使用。

// 定义:计算两数之和,仅内部打印,无返回值 public static void Test1(int a, int b) { int sum = a + b; Console.WriteLine(sum); // 只能在方法内输出结果 } // 调用:无法接收返回值 Test1(10, 20); // 直接执行,输出30

2. 有返回值(指定类型)

void替换为具体数据类型(int/string/ 自定义对象等),必须配合return关键字返回数据,return后的值类型必须与方法定义的返回值类型一致。

(1)返回基本类型(int)
// 定义:计算两数之和,返回int类型结果 public static int Test2(int a, int b) { int sum = a + b; return sum; // return 跳出方法,返回结果 } // 调用:接收返回值,可在外部使用 int s1 = Test2(99, 99); Console.WriteLine(s1); // 输出198
(2)返回自定义对象

方法可以返回类的实例对象,实现复杂数据的返回。

// 自定义学生类 public class Student { public string Name { get; set; } } // 定义:返回Student对象 public static Student Test3(string name) { Student student = new Student(); // 实例化对象 student.Name = name; // 赋值属性 return student; // 返回对象 } // 调用:接收对象,访问对象属性 Student zs = Test3("张三"); Console.WriteLine(zs.Name); // 输出张三

3. 实战:三数取最大值

public static int Max(int a, int b, int c) { int temp = a <= b ? b : a; // 先取a、b最大值 int max = temp <= c ? c : temp; // 再与c比较取最大值 return max; } // 调用 Console.WriteLine(Max(1, 1, 9)); // 输出9

二、方法参数传递:值传递

C# 中默认参数传递方式是值传递,值传递的核心是:传递的是数据的副本(拷贝),根据参数类型(值类型 / 引用类型),表现不同。

1. 值类型参数(int/double/bool 等)

传递时,会拷贝实参的值给形参,方法内部修改形参,不会影响外部实参

// 定义:值类型参数 public static void Test1(int a) { a = 20; // 修改的是拷贝的副本 } // 调用 int a1 = 10; Test1(a1); Console.WriteLine(a1); // 输出10,外部值未变

2. 引用类型参数(类 / 对象等)

传递时,拷贝对象的内存地址给形参(形参和实参指向同一个对象),分两种修改场景:

  • 修改对象属性:会影响外部实参(操作的是同一个对象);
  • 重新 new 对象:不会影响外部实参(形参指向新地址,与原对象断开)。
// 自定义人类 public class People { public string Name { get; set; } } // 定义:引用类型参数 public static void Test2(People p) { // 方式1:修改对象属性 → 影响外部 p.Name = "李四"; // 方式2:重新new对象 → 不影响外部 // p = new People() { Name = "李四" }; } // 调用 People p1 = new People() { Name = "张三" }; Test2(p1); Console.WriteLine(p1.Name); // 方式1输出李四,方式2输出张三

值传递总结

  • 值类型:修改形参 → 外部不变;
  • 引用类型:改属性→外部变,重新 new→外部不变。

三、引用传递:ref 关键字

ref引用传递关键字,作用是:让形参和实参指向同一块内存地址,方法内部修改形参,一定会影响外部实参

核心规则

  1. 实参和形参都必须加ref关键字;
  2. 实参必须先初始化(赋值)才能传递;
  3. 无论值类型 / 引用类型,修改都会同步到外部。

1. ref 修饰值类型

public static void Test1(ref int a) { a = 20; // 直接修改原数据 } // 调用:实参必须初始化 int a1 = 10; Test1(ref a1); Console.WriteLine(a1); // 输出20,外部值被修改

2. ref 修饰引用类型

无论改属性还是重新 new 对象,都会影响外部实参:

public static void Test2(ref People a) { // 方式1:改属性 → 外部变 // a.Name = "武大郎"; // 方式2:重新new → 外部也变 a = new People() { Name = "武大郎" }; } // 调用 People p1 = new People() { Name = "烧饼" }; Test2(ref p1); Console.WriteLine(p1.Name); // 输出武大郎

四、引用传递:out 输出参数

out也是引用传递关键字,核心作用:让方法返回多个结果,同时具备引用传递特性。

核心规则

  1. 实参和形参都必须加out关键字;
  2. 实参可以不初始化
  3. 方法内部必须给 out 参数赋值(负责传出数据)。

ref 与 out 区别(重点)

特性refout
实参初始化必须赋值可以不赋值
方法内赋值可以不赋值必须赋值
主要用途传入 + 传出数据专门传出多个数据
// 定义:out参数实现多返回值 public static void Test1(out int a, out int b) { a = 90; // 方法内必须赋值 b = 90; a = a + b; // 180 b = (a - b) * b; // 8100 } // 调用 int a1 = 30; // 可初始化,也可不写 int b1 = 40; Test1(out a1, out b1); Console.WriteLine($"a1={a1}, b1={b1}"); // 输出a1=180, b1=8100

五、只读参数:in 关键字

in只读引用传递关键字,作用:以高效的引用方式传递参数,且禁止修改形参本身

核心规则

  1. 修饰值类型:禁止修改形参的值;
  2. 修饰引用类型:禁止重新new形参(修改指向),但可以修改对象属性
// 1. in修饰值类型:只读,不能修改 public static void Test1(in int a) { // a = 100; ❌ 报错:只读参数无法赋值 int sum = a + 19; Console.WriteLine(sum); // 仅可读 } // 2. in修饰引用类型:可改属性,不可重新new public static void Test2(in People a) { a.Name = "foo"; // ✅ 允许修改属性 // a = new People() { Name = "foo" }; ❌ 报错:禁止修改指向 }

六、可变参数:params 关键字

params关键字用于定义可变长度参数列表,允许传递任意数量的同类型参数,底层会自动封装成数组。

核心规则

  1. params必须修饰数组(如params int[]);
  2. 一个方法只能有一个params参数,且必须放在参数列表最后;
  3. 调用时可直接传多个值,无需手动创建数组。
// 1. 纯params参数:接收任意数量int public static void Test1(params int[] a) { // 遍历所有参数 for (int i = 0; i < a.Length; i++) { Console.WriteLine(a[i]); } } // 2. 普通参数+params参数(params放最后) public static void Test2(int a, int b, params int[] c) { Console.WriteLine(c[0]); // 取params数组第一个值 } // 调用 Test1(1, 2, 4, 44); // 传递任意数量参数 Test2(10, 20, 30, 40, 50); // a=10,b=20,c=[30,40,50]

七、全流程总结(必背)

  1. 返回值void无返回,指定类型需return,可返回基本类型 / 对象;
  2. 值传递(默认):传副本,值类型修改不影响外部,引用类型改属性影响、new 不影响;
  3. ref:引用传递,实参必须初始化,修改同步外部,用于传入 + 传出;
  4. out:引用传递,实参可不初始化,方法内必须赋值,用于多返回值;
  5. in:只读引用,禁止修改形参本身,可改引用类型属性;
  6. params:可变参数,封装为数组,放参数列表最后。

总结

  1. 方法返回值分无返回(void)和有返回(return+指定类型),支持返回对象实现复杂数据输出;
  2. 默认值传递:值类型改不动外部,引用类型改属性有效、new 无效;
  3. ref/out是引用传递,ref传值 + 传出,out专用于多返回值;
  4. in实现只读引用,params实现任意数量参数,灵活适配不同业务场景。
http://www.gsyq.cn/news/1333470.html

相关文章:

  • 谷歌运营公司热门推荐
  • 电池模型参数辨识避坑指南:HPPC数据拟合时,你的1RC和2RC模型初始值设对了吗?
  • 基于PIC单片机与PWM的RGB LED光效控制:从电路设计到低功耗优化
  • 2026年智能锁电池选购指南(详细版)
  • 5.20 明天见!拿好这份参会指南|AIGC2026峰会
  • 抢先李飞飞!世界模型能多人联机玩FPS游戏了
  • 别再傻傻分不清了!用大白话+真实案例讲透OAuth 2.0和OIDC到底差在哪
  • 意图共鸣科技《AI记忆链商业化白皮书2.0》认知锚定:为什么新概念需要“老参照”
  • 2026 年 GEO 优化服务商TOP5排行榜:如何找到适合自己的geo服务商?geo服务内容介绍? - 互联网科技品牌测评
  • 为你的企业构建第一个 AI Agent Harness Engineering 的步骤
  • Envoy 详解:云原生时代的高性能网络代理
  • Claude Code 深度工程实践:从个人编码助手到企业级 Agent 工程平台
  • 国内开通 GPT 会员的自助充值流程记录
  • 深度解析:Cursor设备标识重置技术核心实现
  • 股价翻倍、港股招股书失效,东山精密是“制造平台化”神话,还是过度幻想?
  • 2026年空气悬浮风机厂家深度测评:如何为工业场景匹配最佳方案? - 资讯速览
  • 串联型工业机器人抗扰动控制技术【附代码】
  • 周奕成(中国武术散打运动员)
  • 为什么你做的RAG总是翻车?三个坑让你怀疑人生
  • 别再只会用plot画图了!用Matlab ode45求解微分方程时,这3种可视化技巧让结果更清晰
  • 2026专业医疗建筑设计公司推荐:破解复杂场景痛点 筑就安全医疗空间 - 资讯速览
  • 代码随想录算法训练营第六十天|Bellman_ford 队列优化算法、Bellman_ford之判断负权回路、bellman_ford之单源有限最短路
  • 2026年最容易上手的5个AI副业
  • 智慧校园软件选型怎么避免踩坑?常见失败原因解析
  • ResNet18实战复盘:我在驾驶分心检测数据集上踩过的那些坑(数据增强、过拟合与可视化)
  • 告别黑箱:用MATLAB手把手教你在线辨识电池模型参数(附NEDC工况数据)
  • 2026虾火锅底料批发权威指南:高性价比供应商测评推荐 - 资讯速览
  • 时间序列自监督学习避坑指南:从SimCLR到MAE,三大流派怎么选?
  • 【计算机组成原理】无符号整数乘法原理(基于移位累加,零基础看懂CPU乘法)
  • 通过curl命令直接测试Taotoken多模型聚合API的响应