当前位置: 首页 > 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.jsqmd.com/news/854260/

相关文章:

  • 别再手动点选了!用C#给NX二次开发控件加过滤器,效率翻倍(附两种方法对比)
  • 《CVPR2025-DEIM创新改进项目实战:从原理到部署的深度学习优化全攻略》007、数据准备——ImageNet/COCO数据集预处理与增强策略
  • 电池模型参数辨识避坑指南:HPPC数据拟合时,你的1RC和2RC模型初始值设对了吗?
  • 将Taotoken接入Node.js后端服务,为应用添加智能对话能力
  • Perplexity读书笔记生成效率提升300%:从零到精通的7步工作流拆解
  • 综合能源系统运行状态分析与仿真计算方法【附代码】
  • 意图共鸣科技《AI记忆链商业化白皮书2.0》认知锚定:为什么新概念需要“老参照”
  • 2026 年 GEO 优化服务商TOP5排行榜:如何找到适合自己的geo服务商?geo服务内容介绍? - 互联网科技品牌测评
  • 破壁端网协同:通感一体化(ISAC)如何重构具身智能的“上帝视角”
  • Envoy 详解:云原生时代的高性能网络代理
  • 当GPT-3成为你的领域专家:无监督概念瓶颈模型在ImageNet上的落地思考
  • 意图共鸣科技《AI记忆链商业化白皮书2.0》优雅降级:停机了,但通讯录还在
  • Claude Code 深度工程实践:从个人编码助手到企业级 Agent 工程平台
  • GEO服务商选型攻略:2026 年 GEO 优化服务商如何选?按不同阶段、行业、需求精准匹配指南,附服务介绍 - 互联网科技品牌测评
  • 英雄联盟Akari助手:5个必用功能彻底改变你的游戏方式
  • 如何轻松配置Windows和Office:面向新手的终极解决方案指南
  • 基于 Google Forms 的新型信任型钓鱼攻击机理与防御体系研究
  • 2026年空气悬浮风机厂家深度测评:如何为工业场景匹配最佳方案? - 资讯速览
  • 破解螺母点焊自动化痛点:上海冈兴螺母输送机PASS定制方法论如何提升产能? - 资讯速览
  • 给STM32F407的OLED显示加点料:手把手教你用HAL库I2C显示中文和自定义图形
  • 别只看低价 辽宁眼镜店真正该比的5件事 - 资讯速览
  • 20260520 2
  • 基于 Google 基础设施滥用的加密货币钓鱼攻击机理与防御研究
  • CLup使用:一键创建Doris存算一体集群
  • Linux I2C驱动框架深度解析:从协议原理到设备驱动实战
  • 第二次作业-VLAN-混杂接口综合实验
  • 中央电化教育馆证书培训机构哪家好?正规授权机构首选中山优才教育 - 优选机构推荐
  • 2026年国内GEO公司选型指南:五强实力对比+中立客观可量化维度测评+场景选型排行榜+FAQ - 互联网科技品牌测评
  • 今日算法(二叉树剪枝)
  • 别再只会用plot画图了!用Matlab ode45求解微分方程时,这3种可视化技巧让结果更清晰