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

C# 方法(值参数和引用参数)

本章内容:
方法的结构
方法体内部的代码执行
局部变量
局部常量
控制流
方法调用
返回值
返回语句和void方法
局部函数
参数
值参数
引用参数
引用类型作为值参数和引用参数
输出参数
参数数组
参数类型总结
方法重载
命名参数
可选参数
栈帧
递归

值参数

参数有几种,各自以略微不同的方式从方法传入或传出数据。到目前为止,你看到的这种类
型是默认的类型,称为值参数(valueparameter)。

当你使用值参数时,通过将实参的值复制到形参的方式把数据传递给方法。方法被调用时,
系统执行如下操作。

在栈中为形参分配空间。
将实参的值复制给形参。

值参数的实参不一定是变量,它可以是任何能计算成相应数据类型的表达式。例如,下面的
代码展示了两个方法调用。在第一个方法调用中,实参是float类型的变量;在第二个方法调用
中,实参是计算成float的表达式。

float func1(float val)     //申明方法
{float j=2.6F;float k=5.1F;...
}

image

float fValue1=func1(k);     //方法调用
float fValue2=func1((k+j)/3);//方法调用

image

用作实参之前,变量必须被赋值(除非是输出参数,稍后会介绍)。对于引用类型,变量可
以被设置为一个实际的引用或null。

说明 所谓值类型就是指类型本身包含其值。不要把值类型
和这里介绍的值参数混淆,它们是完全不同的两个概念。值参数是把实参的值复制给
形参。

例如,下面的代码展示了一个名为MyMethod的方法,它有两个参数:一个MyClass类型的变
量和一个int。

方法为类的int类型字段和参数都加上5。
你可能还注意到MyMethod使用了修饰符static,我们还没有解释过这个关键字,现在你
可以忽略它。

class MyClass
{public int Val=20;      //初始化字段为20
}class Program
{static void MyMethod(MyClass f1,int f2){f1.Val=f1.Val+5;     //参数的字段加5f2    =f2+5;         //另一参数加5}static void Main(){MyClass a1=new MyClass();int a2=10;MyMethod(a1,a2);Console.WriteLine($"a1.Val:{a1.Val},a2:{a2}");}
}

image
图6-7展示了实参和形参在方法执行的不同阶段的值,它表明了以下3点。
在方法被调用前,用作实参的变量a2已经在栈里了。
在方法开始时,系统在栈中为形参分配空间,并从实参复制值。
因为a1是引用类型的,所以引用被复制,结果实参和形参都引用堆中的同一个对象。
因为a2是值类型的,所以值被复制,产生了一个独立的数据项。
在方法的结尾,f2和对象f1的字段都被加上了5。
方法执行后,形参从栈中弹出。
到a2,值类型,它的值不受方法行为的影响。
a1,引用类型,但它的值被方法的行为改变了。

值参数

第二种参数类型称为引用参数。
使用引用参数时,必须在方法的声明和调用中都使用ref修饰符。
实参必须是变量,在用作实参前必须被赋值。如果是引用类型变量,可以赋值为一个引
用或null。
例如,下面的代码阐明了引用参数的声明和调用的语法:

void MyMethod(ref int val)   //方法申明
{...}int y=1;                     //实参变量
MyMethod(ref y);             //方法调用MyMethod(ref 3+5);           //出错了

image

不会在栈上为形参分配内存。
形参的参数名将作为实参变量的别名,指向相同的内存位置。
由于形参名和实参名指向相同的内存位置,所以在方法的执行过程中对形参做的任何改变在
方法完成后依然可见(表现在实参变量上)。

说明 记住要在方法的声明和调用上都使用ref关键字。

例如,下面的代码再次展示了方法MyMethod,但这一次参数是引用参数而不是值参数。

class MyClass
{public int Val=20;       //初始化字段为20
}class Program
{static void MyMethod(ref MyClass f1,ref int f2){f1.Val=f1.Val+5;       //参数的字段加5f2    =f2+5;           //另一参数加5Console.WriteLine($"f1.Val:{f1.Val},f2:{f2}");}static void Main(){MyClass a1=new MyClass();int a2= 10;MyMethod(ref a1,ref a2);Console.WriteLine($"a1.Val:{a1.Val},a2:{a2}");}
}

image
注意,不管MyClass对象f1是否是通过ref传递给方法,fl.val的值都是相同的。稍后会
对此进行详细的讨论。
图6-8阐明了在方法执行的不同阶段实参和形参的值。
在方法调用之前,将要被用作实参的变量a1和a2已经在栈里了。
在方法的开始,形参名被设置为实参的别名。变量a1和f1引用相同的内存位置,a2和
f2引用相同的内存位置。
在方法的结束位置,f2和f1的对象的字段都被加上了5。
方法执行之后,形参的名称已经失效,但是值类型a2的值和引用类型a1所指向的对象的
值都被方法内的行为改变了。

对于引用参数,形参就像实参的别名

http://www.xdnf.cn/news/4195.html

相关文章:

  • mysql 如何查询数据库链接日志
  • Spring 中四种常见初始化方法,对比 static {} 和 @PostConstruct 在并发,Spring 加载顺序大致为: JVM 加载类
  • 生成了一个AI算法
  • 网络安全的范式革命:从被动防御到 AI 驱动的主动对抗
  • 基于大模型的自然临产阴道分娩全流程预测与方案研究报告
  • 开个帖子记录一下自己学spring源码的过程
  • Spyglass:官方Hands-on Training(三)
  • 数据中台架构设计
  • c++类【发展】
  • 【全面解析】Poco C++ Libraries 模块详解与使用指南
  • UE5 使用插件进行Audio2face和UE5的实时链接并实时输出嘴型
  • 多模态训练与微调
  • 突破v0.dev对话限制的两种方法
  • k8s node 报IPVS no destination available
  • 19.第二阶段x64游戏实战-vector容器
  • 二叉树的最大深度(简单)
  • 标题:基于自适应阈值与K-means聚类的图像行列排序与拼接处理
  • LintCode第484题-交换数组两个元素,第9题-Fizz Buzz 问题,第46题-主元素,第50题数组剔除元素后的乘积
  • 超表面加工流程
  • 从零开始了解数据采集(二十二)——塑胶制品行业趋势分析案例
  • (leetcode) 力扣100 6.三数之和 (双指针)
  • 卷积神经网络的简单实战项目
  • 大模型——GraphRAG基于知识图谱+大模型技术构建的AI知识库系统
  • 怎样用 esProc 实现多数据库表的数据合并运算
  • 深入理解 Linux 阻塞IO与Socket数据结构
  • 《脑机接口与AI:如何让瘫痪患者用“意念”实现创作?》
  • 在 PyTorch 中借助 GloVe 词嵌入完成情感分析
  • 【Vue】组件自定义事件 TodoList 自定义事件数据传输
  • Spring Boot3 实现定时任务 每10分钟执行一次,同时要解决分布式的问题 区分不同场景
  • 【coze】意图识别(售前售后问题、搜索引擎去广告)