【C#基础】函数传参大总结
目录
- 前言
- 参数是值类型的情况
- 1. 按值传递(Pass by Value)
- 2. 按引用传递(Pass by Reference)
- 使用 `ref`
- 使用 `in`
- 3. 输出参数传递(Output Parameters)
- 参数修饰符对比
- 小结
- 参数是引用类型的情况
- 1. 按值传递类对象
- 虽然类是引用类型,但默认情况下将类对象传递给函数时,传递的仍是`引用的副本`。
- 2. 按引用传递类对象(`ref`)
- 3. 使用 `out` 参数
- 4. 使用 `in` 参数
- 小结
- 虽然类是引用类型,但默认情况下将类对象传递给函数时,传递的仍是`引用的副本`。
- 最后一问
- 如果传递的是结构体呢?
前言
在C#中,函数传参有三种主要的方式:按值传递、按引用传递和输出参数传递。每种方式的使用场景和效果都不同,下面我将详细讲解这三种方式。
参数是值类型的情况
1. 按值传递(Pass by Value)
这是最常见的参数传递方式。默认情况下,C# 函数的参数是按值传递的。这意味着调用函数时,实参的值会被复制到形参,因此对形参的修改不会影响实参。
void ModifyValue(int x)
{x = 10;
}int number = 5;
ModifyValue(number);
Console.WriteLine(number); // 输出: 5
在这个例子中,number
的值并不会因为函数内部的修改而改变,因为 x
只是 number
的副本。
2. 按引用传递(Pass by Reference)
通过使用 ref
或 in
关键字,可以按引用传递参数。按引用传递时,传递的不是值的副本,而是变量本身的引用。函数可以直接修改原始变量的值。
使用 ref
ref
关键字允许函数修改传递进来的参数的值,并且要求传入的参数必须先初始化。
void ModifyRef(ref int x)
{x = 10;
}int number = 5;
ModifyRef(ref number);
Console.WriteLine(number); // 输出: 10
在这个例子中,number
的值被函数修改了,因为 ref
让参数传递的是引用。
使用 in
in
关键字表示按引用传递,但参数只能在函数内部读取,不能修改。
void ReadValue(in int x)
{Console.WriteLine(x);// x = 10; // 编译错误,不能修改 in 参数
}int number = 5;
ReadValue(in number);
in
参数保证了函数不能修改传递进来的值,只能读取。这对于需要高效传递大型数据结构而不希望其被修改时特别有用。
3. 输出参数传递(Output Parameters)
out
关键字允许函数返回多个值或将数据传递回调用者。与 ref
类似,out
也是按引用传递的,但它不要求变量在传入时已经初始化。函数必须在返回前给 out
参数赋值。
void GetValues(out int x, out int y)
{x = 10;y = 20;
}int a, b;
GetValues(out a, out b);
Console.WriteLine(a); // 输出: 10
Console.WriteLine(b); // 输出: 20
在这个例子中,a
和 b
的值在函数内部被初始化并返回给调用者。
参数修饰符对比
- 按值传递(默认):函数对形参的修改不会影响实参。
ref
:传递引用,形参和实参指向同一个变量,函数可以修改原始变量。in
:按引用传递,但函数只能读取,不可修改。out
:函数必须对参数赋值,用于返回多个值。
小结
C# 提供了灵活的参数传递方式,开发者可以根据需求选择是按值传递、按引用传递还是使用 out
进行输出。这些方式为开发高效、安全的代码提供了很大的帮助。
参数是引用类型的情况
和C++不同,C#的任何class对象都是引用。
在C#中,如果传递的是类对象,情况会有所不同,因为类是引用类型。当你把类对象作为参数传递给函数时,不论是按值传递还是按引用传递,都会对类对象的行为产生影响。让我们仔细看一下如何处理类对象的传递。
1. 按值传递类对象
虽然类是引用类型,但默认情况下将类对象传递给函数时,传递的仍是引用的副本
。
这意味着函数内部对对象属性的修改将会影响到原始对象,因为引用指向的是同一个对象。但如果函数试图重新分配整个对象的引用,外部对象则不会受到影响。
class Person
{public string Name { get; set; }
}void ModifyPerson(Person p)
{p.Name = "Alice"; // 修改属性
}Person person = new Person { Name = "Bob" };
ModifyPerson(person);
Console.WriteLine(person.Name); // 输出: Alice
在上面的例子中,虽然是按值传递,但类对象是引用类型,因此 person
和 p
都引用同一个对象,修改了 p.Name
也会修改 person.Name
。
然而,如果在函数内部重新赋值引用,外部的对象将不会改变:
void ReassignPerson(Person p)
{p = new Person { Name = "Charlie" }; // 重新分配引用
}Person person = new Person { Name = "Bob" };
ReassignPerson(person);
Console.WriteLine(person.Name); // 输出: Bob
在这个例子中,函数内部重新分配了 p
的引用,但这不会影响到外部的 person
对象,因为传递的引用本身是按值传递的副本。
2. 按引用传递类对象(ref
)
使用 ref
关键字时,可以将对象的引用本身传递给函数。这意味着函数可以重新分配对象,并让外部变量反映这种变化。
void ReassignPersonRef(ref Person p)
{p = new Person { Name = "Charlie" }; // 重新分配引用
}Person person = new Person { Name = "Bob" };
ReassignPersonRef(ref person);
Console.WriteLine(person.Name); // 输出: Charlie
在这个例子中,函数通过 ref
传递引用,因此 person
现在指向新的 Person
对象。
3. 使用 out
参数
out
参数的行为与 ref
类似,但要求在函数内部必须对传入的参数赋值。适用于需要从函数返回新的对象或初始化传递进来的对象。
void InitializePerson(out Person p)
{p = new Person { Name = "David" }; // 必须初始化
}Person person;
InitializePerson(out person);
Console.WriteLine(person.Name); // 输出: David
这里,person
是通过 out
参数传递,函数内部必须为其分配一个新对象。
4. 使用 in
参数
in
参数用于按引用传递对象,但它确保对象的引用在函数内部不能被修改。函数可以读取对象的属性和方法,但不能更改引用本身。对于大型对象,它可以避免复制操作,提高效率。
void ReadPerson(in Person p)
{Console.WriteLine(p.Name); // 读取属性是允许的// p = new Person(); // 编译错误,不能修改引用
}Person person = new Person { Name = "Eva" };
ReadPerson(in person);
小结
虽然类是引用类型,但默认情况下将类对象传递给函数时,传递的仍是引用的副本
。
如果能理解这句话,不管是哪种情况,那么思想上就是统一的。
最后一问
如果传递的是结构体呢?
在C#中,**结构体(struct)与类(class)**有一个重要的区别:结构体是值类型,而类是引用类型。因此,如果是结构体,请参考 参数是值类型的情况 !
相关文章:
【C#基础】函数传参大总结
目录 前言参数是值类型的情况1. 按值传递(Pass by Value)2. 按引用传递(Pass by Reference)使用 ref使用 in 3. 输出参数传递(Output Parameters)参数修饰符对比小结 参数是引用类型的情况1. 按值传递类对象…...

初学51单片机之IO口上下拉电阻相关
本案本来是描述一下I2C总线的,在此之前推荐一下B站一个UP关于时序图的讲解 I2C入门第一节-I2C的基本工作原理_哔哩哔哩_bilibili 不过在描述I2C前先简单的探讨下51单片机IO口下拉电阻的基本情况,事实上这个问题困扰笔者很长时间了,这次也是一…...

Resnet50网络——口腔癌病变识别
一 数据准备 1.导入数据 import matplotlib.pyplot as plt import tensorflow as tf import warnings as w w.filterwarnings(ignore) # 支持中文 plt.rcParams[font.sans-serif] [SimHei] # 用来正常显示中文标签 plt.rcParams[axes.unicode_minus] False # 用来正常显示负…...
Python 中自动打开网页并点击[自动化脚本],Selenium
要在 Python 中自动打开网页并点击第一个 <a> 标签,你需要使用 Selenium,它可以控制浏览器并执行像点击这样的操作。requests 和 BeautifulSoup 只能获取并解析网页内容,但不能进行网页交互操作。 步骤: 安装 Selenium安装…...
Spring Boot-自动配置问题
**### Spring Boot自动配置问题探讨 Spring Boot 是当前 Java 后端开发中非常流行的框架,其核心特性之一便是“自动配置”(Auto-Configuration)。自动配置大大简化了应用开发过程,开发者不需要编写大量的 XML 配置或是繁琐的 Jav…...

CS61B学习 part1
本人选择了2018spring的课程,因为他免费提供了评分机器,后来得知2021也开放了,决定把其中的Lab尝试一番,听说gitlab就近好评,相当有实力,并借此学习Java的基本知识,请根据pku的cswiki做好评分机…...
我Github的问题解决了!
看的这篇,解决使用git时遇到Failed to connect to github.com port 443 after 21090 ms: Couldn‘t connect to server_git couldnt connect to server-CSDN博客 之前想推送的能推送了,拉取的也能取了。 一、如果是在挂着梯子的情况下拉取或者推送代码…...
Pytorch构建神经网络多元线性回归模型
1.模型线性方程y W ∗ X b from torch import nn import torch#手动设置的W参数(待模型学习),这里设置为12个,自己随意设置weight_settorch.tensor([[1.5,2.38,4.22,6.5,7.2,3.21,4.44,6.55,2.48,-1.75,-3.26,4.78]])#手动设置…...

如何基于Flink CDC与OceanBase构建实时数仓,实现简化链路,高效排查
本文作者:阿里云Flink SQL负责人,伍翀,Apache Flink PMC Member & Committer 众多数据领域的专业人士都很熟悉Apache Flink,它作为流式计算引擎,流批一体,其核心在于其强大的分布式流数据处理能力&…...

ActiveMQ、RabbitMQ 和 Kafka 在 Spring Boot 中的实战
在现代的微服务架构和分布式系统中,消息队列 是一种常见的异步通信工具。消息队列允许应用程序之间通过 生产者-消费者模型 进行松耦合、异步交互。在 Spring Boot 中,我们可以通过简单的配置来集成不同的消息队列系统,包括 ActiveMQ、Rabbit…...

火语言RPA流程组件介绍--获取关联元素
🚩【组件功能】:获取指定元素的父元素、子元素、相邻元素等关联信息 配置预览 配置说明 目标元素 支持T或# 默认FLOW输入项 通过自动捕获工具捕获(选择元素工具使用方法)或手动填写网页元素的css,xpath,指定对应网页元素作为操作目标 关联…...

【2024研赛】【华为杯E题】2024 年研究生数学建模比赛思路、代码、论文助攻
思路将在名片下群聊分享 高速公路应急车道紧急启用模型 高速公路拥堵现象的原因众多,除了交通事故外,最典型的就是部分路段出现瓶颈现象,主要原因是车辆汇聚,而拥堵后又容易蔓延。高速公路一些特定的路段容易形成堵点࿰…...

Linux——K8s集群部署过程
1、环境准备 (1)配置好网络ip和主机名 control: node1: node2: 配置ip 主机名的过程省略 配置一个简单的基于hosts文件的名称解析 [rootnode1 ~]# vim /etc/hosts // 文件中新增以下三行 192.168.110.10 control 192.168.110.11 node1 1…...

二.Unity中使用虚拟摇杆来控制角色移动
上一篇中我们完成了不借助第三方插件实现手游的虚拟摇杆,现在借助这个虚拟摇杆来实现控制角色的移动。 虚拟摇杆实际上就给角色输出方向,类似于键盘的WSAD,也是一个二维坐标,也就是(-1,1)的范围,将摇杆的方向进行归一化…...

基于SpringBoot的旅游管理系统
系统展示 用户前台界面 管理员后台界面 系统背景 近年来,随着社会经济的快速发展和人民生活水平的显著提高,旅游已成为人们休闲娱乐、增长见识的重要方式。国家积极倡导“全民旅游”,鼓励民众利用节假日外出旅行,探索各地自然与人…...
Linux套接字
目录标题 套接字套接字的基本概念套接字的功能与分类套接字的使用流程套接字的应用场景总结套接字在不同操作系统中的实现差异有哪些?如何优化套接字编程以提高网络通信的效率和安全性?原始套接字(SOCK_RAW)的具体应用场景和使用示…...
软件测试面试题(5)——二面(游戏测试)
没想到测试题做完等了会儿就安排面试了,还以为自己会直接挂在测试题,这次面试很刺激。测试题总体来说不算太难,主要是实操写Bug那里真没经历过,所以写的很混乱。 我复盘一下这次面试的问题,这次面试是有两个面试官&…...

C#基于SkiaSharp实现印章管理(8)
上一章虽然增加了按路径绘制文本,支持按矩形、圆形、椭圆等路径,但测试时发现通过调整尺寸、偏移量等方式不是很好控制文本的位置。相对而言,使用弧线路径,通过弧线起始角度及弧线角度控制文本位置更简单。同时基于路径绘制文本时…...

信通院发布首个《大模型媒体生产与处理》标准,阿里云智能媒体服务作为业界首家“卓越级”通过
中国信通院近期正式发布《大模型驱动的媒体生产与处理》标准,阿里云智能媒体服务,以“首批首家”通过卓越级评估,并在9大模块50余项测评中表现为“满分”。 当下,AI大模型的快速发展带动了爆发式的海量AI运用,这其中&a…...
AI学习指南深度学习篇-Adam的Python实践
AI学习指南深度学习篇-Adam的Python实践 在深度学习领域,优化算法是影响模型性能的关键因素之一。Adam(Adaptive Moment Estimation)是一种广泛使用的优化算法,因其在多种问题上均表现优异而被广泛使用。本文将深入探讨Adam优化器…...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...
Java 加密常用的各种算法及其选择
在数字化时代,数据安全至关重要,Java 作为广泛应用的编程语言,提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景,有助于开发者在不同的业务需求中做出正确的选择。 一、对称加密算法…...

多种风格导航菜单 HTML 实现(附源码)
下面我将为您展示 6 种不同风格的导航菜单实现,每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...

CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)
漏洞概览 漏洞名称:Apache Flink REST API 任意文件读取漏洞CVE编号:CVE-2020-17519CVSS评分:7.5影响版本:Apache Flink 1.11.0、1.11.1、1.11.2修复版本:≥ 1.11.3 或 ≥ 1.12.0漏洞类型:路径遍历&#x…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf
FTP 客服管理系统 实现kefu123登录,不允许匿名访问,kefu只能访问/data/kefu目录,不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...

【Redis】笔记|第8节|大厂高并发缓存架构实战与优化
缓存架构 代码结构 代码详情 功能点: 多级缓存,先查本地缓存,再查Redis,最后才查数据库热点数据重建逻辑使用分布式锁,二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...

Razor编程中@Html的方法使用大全
文章目录 1. 基础HTML辅助方法1.1 Html.ActionLink()1.2 Html.RouteLink()1.3 Html.Display() / Html.DisplayFor()1.4 Html.Editor() / Html.EditorFor()1.5 Html.Label() / Html.LabelFor()1.6 Html.TextBox() / Html.TextBoxFor() 2. 表单相关辅助方法2.1 Html.BeginForm() …...

uniapp 开发ios, xcode 提交app store connect 和 testflight内测
uniapp 中配置 配置manifest 文档:manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号:4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...
Linux系统部署KES
1、安装准备 1.版本说明V008R006C009B0014 V008:是version产品的大版本。 R006:是release产品特性版本。 C009:是通用版 B0014:是build开发过程中的构建版本2.硬件要求 #安全版和企业版 内存:1GB 以上 硬盘…...