C# 图解教程 第5版 —— 第6章 方法

news2024/12/1 0:32:19

文章目录

    • 6.1 方法的结构
    • 6.2 方法体内部的代码执行
    • 6.3 局部变量
      • 6.3.1 类型推断和 var 关键字
      • 6.3.2 嵌套块中的局部变量
    • 6.4 局部常量
    • 6.5 控制流
    • 6.6 方法调用(*)
    • 6.7 返回值(*)
    • 6.8 返回语句和 void 方法
    • 6.9 局部函数
    • 6.10 参数(*)
    • 6.11 值参数
    • 6.12 引用参数
    • 6.13 引用类型作为值参数和引用参数
    • 6.14 输出参数
    • 6.15 参数数组
      • 6.15.1 方法调用
      • 6.15.2 将数组作为实参
    • 6.16 参数类型总结
    • 6.17 ref 局部变量和 ref 返回
    • 6.18 方法重载
    • 6.19 命名参数
    • 6.20 可选参数
    • 6.21 栈帧
    • 6.22 递归(*)

6.1 方法的结构

  • 返回的数据类型。
  • 方法名称。
  • 参数列表。
image-20231015165612625
图6.1 方法的结构

6.2 方法体内部的代码执行

​ 方法体是一个块,可以包含以下内容:

  • 局部变量;
  • 控制流结构;
  • 方法调用;
  • 内嵌的块;
  • 其他方法(局部函数)。

6.3 局部变量

  • 局部变量的生存周期仅限于创建它的块内。
    • 声明时开始存在。
    • 块尾结束存在。
  • 可以在方法体内部任意位置声明,声明后才能使用。
image-20231015165958072
图6.2 对比实例字段和局部变量

6.3.1 类型推断和 var 关键字

​ 使用 var 关键字可以进行类型推断,而不需要明确指定变量类型。var 关键字并不改变 C# 的强类型性质。

  • 只能用于局部变量,不能用于字段。
  • 只能在变量声明中包含初始化时使用。
  • 一旦编译器推断出变量的类型,它就是固定且不能更改的。

6.3.2 嵌套块中的局部变量

​ 在 C# 中不论嵌套级别如何,都不能在第一个名称的有效范围内声明另一个同名的局部变量。

6.4 局部常量

  • 声明时必须初始化。
    • 初始化值必须在编译时就可以确定,通常为预定义简单类型或 null 引用。
  • 声明后不能改变。

​ 和局部变量一样,局部常量声明在方法体或代码块里,并在声明它的块结束的地方失效。

​ 注意:const 不是修饰符,而是核心声明的一部分。

6.5 控制流

  • 选择语句
    • if
    • if … else
    • switch
  • 迭代语句
    • for
    • while
    • do
    • foreach
  • 跳转语句
    • break
    • continue
    • goto
    • return

6.6 方法调用(*)

6.7 返回值(*)

6.8 返回语句和 void 方法

6.9 局部函数

​ C# 7.0 开始,可以在一个方法中声明另一个单独的方法,称为局部函数。

6.10 参数(*)

6.11 值参数

​ 使用值参数时,会发生如下操作:

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

​ 方法使用值参数不能改变原始的值类型数据,但是可以改变引用类型的数据:

class MyClass { public int Val = 20; }

class Program {
    static void MyMethod(MyClass f1, int f2) { // 形参
        f1.Val = f1.Val + 5;
        f2     = f2 + 5;
    }
    
    static void Main() {
        MyClass a1 = new MyClass();
        int a2 = 10;
        MyMethod(a1, a2); // 实参
    }
}
image-20231015185433612
图6.3 值参数

6.12 引用参数

  • 在方法的声明和调用中都使用 ref 修饰符。
  • 实参必须是已经被赋值的变量,引用类型变量可以是 null。
image-20231015185911962
图6.4 ref 使用说明

​ 引用参数具有如下特征:

  • 不会在栈上为形参分配内存。
  • 形参的参数名将作为实参变量的别名,指向相同的内存位置。
image-20231015190030549
图6.5 对于引用参数,形参就像实参的别名

6.13 引用类型作为值参数和引用参数

​ 对于引用类型对象:

  • 作为值参数传递:如果在方法内创建一个新对象并赋值给形参,对实参没有影响。
  • 作为引用参数传递:如果在方法内创建一个新对象并赋值给形参,则实参也会随之改变。
image-20231015190519645
图6.6 对用作值参数的引用类型对象赋值
image-20231015190632315
图6.7 为用作引用参数的引用类型对象赋值

​ 将引用类型对象作为引用参数传递,目的是改变引用对象;

​ 如果仅需改变引用类型对象的内容,只需值参数传递即可。

6.14 输出参数

  • 在方法的声明和调用中都使用 out 修饰符。
  • 实参必须是变量,使用前可以不赋值。
  • 形参的参数名也作为实参变量的别名,指向相同的内存位置。
image-20231015190939239
图6.8 out 使用说明

​ 与 ref 不同,out 有如下要求:

  1. 给输出参数赋值后才能读取。
  2. 方法返回之前,必须给输出参数赋值。

​ C# 7.0 后,可以对输出参数进行简化声明,不需要预先声明一个变量来用作 out 参数了。如图 6.9 所示,声明后的 a1 和 a2 可以在方法调用结束后继续使用。

image-20231015191333370
图6.9 out 新的声明方式

6.15 参数数组

  • 在形参前使用 params 修饰符,并在数据类型后放置一组方括号。
  • 参数列表中只能有一个参数数组,且必须为参数列表的最后一个。
  • 参数数组中的所有参数类型必须相同。
image-20231015191753290
图6.10 params 使用说明

6.15.1 方法调用

​ 可以使用两种方式为参数数组提供实参:

  1. 使用逗号分隔的元素列表。
ListInts(10, 20, 30); // 3 个 int
  1. 一个同类型的一维数组。
int[] intArray = {1, 2, 3};
ListInts(intArray);

​ 注意:在调用时不使用 params 修饰符。

​ 使用独立实参调用时,编译器将执行以下步骤:

  1. 接受实参列表,在堆中创建并初始化一个数组;
  2. 把数组的引用保存到栈中的形参里;
  3. 如果没有实参(个数为 0),则编译器会创建一个具有 0 个元素的数组来使用。
void ListInts(params int[] inVals) { ... } // 方法声明

...
ListInts();              // 0 个实参
ListInts(1, 2, 3);       // 3 个实参
ListInts(4, 5, 6, 7, 8); // 5 个实参

​ 当数组 inVals 在堆中被创建时,实参的值被赋值到数组中,因此可看做值参数:

  • 数组参数为值类型:值被复制,实参不受影响;
  • 数组参数为引用类型:引用被复制,实参引用的对象在内部会受到影响。
image-20231015192755242
图6.11 参数数组示例

6.15.2 将数组作为实参

​ 编译器将使用传入的数组而不是重新创建一个。

6.16 参数类型总结

image-20231015192951213
图6.12 参数类型语法使用总结

6.17 ref 局部变量和 ref 返回

​ 创建别名的语法需要使用 ref 两次。

image-20231015193051479
图6.13 创建 ref 局部变量

​ ref 返回使得方法可以返回引用而不是值,同样也需要使用两次 ref:

image-20231015193219646
图6.14 ref 返回示例

​ 有关 ref 的使用有如下注意事项:

  1. ref return 不能返回如下内容:
    • 空值。
    • 常量。
    • 枚举成员。
    • 类或结构体的属性。
    • 指向只读位置的指针。
  2. ref return 不能返回方法内部的局部变量;
  3. ref 局部变量只能被赋值一次,后面出现的等号表示赋值;
  4. 如果调用 ref 返回方法时未使用 ref 关键字,则返回的是值而不是引用;
  5. 将 ref 局部变量作为常规的实际参数传递给其他方法时,传递的仍是 ref 指向的副本而不是引用。

6.18 方法重载

​ 使用相同名称的方法必须和其他同名方法有不同的签名,签名由如下信息组成:

  • 方法名称。
  • 参数数目。
  • 参数的数据类型和顺序。
  • 参数修饰符。

​ 返回类型和形参名称都不是签名的一部分。

image-20231015212331455
图6.15 签名组成成分

6.19 命名参数

​ C# 可以使用命名参数,显示指定参数的名称,就能够以任意顺序在方法中列出实参。

image-20231015212314102
图6.16 命名参数示例

​ 可以同时使用位置参数和命名参数,但所有位置参数必须先列出。

image-20231015212232064
图6.17 位置参数和命名参数同时使用

6.20 可选参数

​ 可选参数能够设置参数的默认值,图 6.18 列出了哪些时候能使用可选参数。

image-20231015212147383
图6.18 可选参数只能是值参数类型

​ 所有必填参数需放在可选参数声明之前,params 参数放在可选参数之后,如图 6.19 所示。

image-20231015212530555
图6.19 所有参数声明顺序
  • 必须从可选参数列表的最后向前开始省略,而不是任意省略参数。
  • 如果需要任意省略参数,需要配合命名参数来实现以消除赋值的歧义。
class MyClass {
    double GetCylinderVolume(double radius = 3.0, double height = 4.0) {
        return 3.1416 * radius * radius * height;
    }
    
    static void Main() {
        MyClass mc = new MyCalss();
        double volume;
        
        volume = mc.GetCylinderVolume(3.0, 4.0);    // 位置参数
        volume = mc.GetCylinderVolume(radius: 2.0); // 使用 height 默认值
        volume = mc.GetCylinderVolume(height: 2.0); // 使用 radius 默认值
        volume = mc.GetCylinderVolume();            // 使用两个默认值
    }
}

6.21 栈帧

​ 调用方法时,内存从栈的顶部开始分配,保存和方法关联的一些数据项。这块内存称为方法的栈帧

  • 栈帧包含如下内容:
    • 返回地址,即方法返回时继续执行的位置。
    • 分配内存的参数,即值参数(参数数组,如果有的话)。
    • 和方法调用相关的其他管理数据项。
  • 在方法调用时,整个栈帧都会压入栈。
  • 方法退出时,整个栈帧会从栈上弹出,也称栈展开

6.22 递归(*)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1095596.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

关于数据链路层(初步)

以太网帧格式: 源地址和目的地址是指网卡的硬件地址(也叫MAC地址),长度是48位,是在网卡出厂时固 化的; 帧协议类型字段有三种值,分别对应载荷的形式,有IP、ARP、RARP; …

Go-Python-Java-C-LeetCode高分解法-第十周合集

前言 本题解Go语言部分基于 LeetCode-Go 其他部分基于本人实践学习 个人题解GitHub连接:LeetCode-Go-Python-Java-C 欢迎订阅CSDN专栏,每日一题,和博主一起进步 LeetCode专栏 我搜集到了50道精选题,适合速成概览大部分常用算法 突…

LuaJit交叉编译移植到ARM Linux

简述 Lua与LuaJit的主要区别在于LuaJIT是基于JIT(Just-In-Time)技术开发的,可以实现动态编译和执行代码,从而提高了程序的运行效率。而Lua是基于解释器技术开发的,不能像LuaJIT那样进行代码的即时编译和执行。因此&…

手摸手Redis7配置哨兵模式(一主二从三哨兵)

安装redis #安装gcc yum -y install gcc gcc-c #安装net-tools yum -y install net-tools #官网https://redis.io/ cd /opt/ wget http://download.redis.io/releases/redis-7.0.4.tar.gz 解压至/opt/目录下 tar -zxvf redis-7.0.4.tar.gz -C /opt/ #编译安装 make make ins…

解决“本地计算机上的 mysql 服务启动后停止,某些服务在未由其他服务或程序使用时将自动停止”

电脑在服务中启动mysql报 如果你之前没有修改过数据库相关文件那么执行以下步骤 1.在数据库的根目录删除data文件(删除前最好先备份一下) 2,然后重新创建一个data文件夹 3.点击进入bin目录,点击上面的路径 4.点击后上面路径变蓝…

MATLAB——BP神经网络信号拟合程序

欢迎关注公众号“电击小子程高兴的MATLAB小屋” %% 学习目标:BP神经网络 %% 函数逼近 数据压缩 模式识别 %% 考虑要素:网络层数 输入层的节点数 输出层的节点数 隐含层的节点数 %% 传输函数 训练方法 %% 对信号曲线进行拟合 clear all; cle…

04_led灯闪烁

创建新的项目&#xff0c;步骤和教程2一样&#xff0c;项目结构和创建后的代码如下所示 具体代码如下所示&#xff1a;使用16进制加延迟的方式控制led的亮灭0表示亮1表示灭 #include <REGX52.H> #include <INTRINS.H> void Delay500ms() //11.0592MHz {unsigne…

网页在线打开PDF_网站中在线查看PDF之pdf.js

一、pdf.js简介 PDF.js 是一个使用 HTML5 构建的便携式文档格式查看器。 pdf.js 是社区驱动的&#xff0c;并由 Mozilla 支持。我们的目标是为解析和呈现 PDF 创建一个通用的、基于 Web 标准的平台。 pdf.js 将 PDF 文档转换为 HTML5 Canvas 元素&#xff0c;并使用 JavaScr…

ASAN地址消毒+GCOV覆盖率分析

安全之安全(security)博客目录导读 覆盖率分析汇总 目录 一、代码示例 二、代码编译及运行 三、ASAN地址消毒&#xff08;找到溢出&泄露点&#xff09; 四、GCOV覆盖率分析 ASAN相关详见ASAN(AddressSanitizer)地址消毒动态代码分析 GCOV相关详见GCOV覆盖率分析 现…

Doris入门了解

微信公众号&#xff1a;大数据高性能计算 大数据存储与分析入门学习文档&#xff1a;深入了解 Doris 大数据技术已成为现代数据处理的核心组成部分&#xff0c;为企业提供了更多洞察和决策支持。Doris&#xff08;以前称为Palo&#xff09;是一种用于大规模数据存储和分析的开…

【LeetCode刷题(数据结构与算法)】:完全二叉树的节点个数

完全二叉树 的定义如下&#xff1a;在完全二叉树中&#xff0c;除了最底层节点可能没填满外&#xff0c;其余每层节点数都达到最大值&#xff0c;并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层&#xff0c;则该层包含 1~ 2h 个节点 输入&#xff1a;r…

Megatron-LM GPT 源码分析(二) Sequence Parallel分析

引用 本文基于开源代码 https://github.com/NVIDIA/Megatron-LM &#xff0c;延续上一篇Megatron-LM GPT 源码分析&#xff08;一&#xff09; Tensor Parallel分析 通过对GPT的模型运行示例&#xff0c;从三个维度 - 模型结构、代码运行、代码逻辑说明 对其源码做深入的分析。…

Spring framework Day15:@lmport注解使用

前言 在编程中&#xff0c;import注解通常用于导入外部的类、接口或其他资源&#xff0c;以便在当前代码文件中使用。它可以提供一种简洁、方便的方式来引入外部依赖&#xff0c;并且有以下几个主要的应用场景和好处&#xff1a; 引入外部类/接口&#xff1a;使用import注解可…

2023年最受好评的五款项目计划工具排名揭晓!

近年来&#xff0c;项目计划工具已经成为项目管理中不可或缺的一部分。正确的项目计划工具将帮助您更有效地管理项目&#xff0c;从而改善结果。随着技术的进步&#xff0c;现在有许多强大而通用的项目计划工具可用。展望2023年&#xff0c;以下是你应该考虑的深受好评的五款项…

如何在Linux上安装Tomcat

安装Tomcat的前提是安装好JDK 使用yum安装JDK Liunx的包管理器就如同手机上的应用商城一样&#xff0c;可以在其中下载软件 Linux中的包管理器有很多&#xff1a;yum、apt、pacman...其中yum是centos自带的包管理器 获取与jdk有关的数据包 请注意&#xff1a;i686后缀的为32位操…

DarkGate恶意软件通过消息服务传播

导语 近日&#xff0c;一种名为DarkGate的恶意软件通过消息服务平台如Skype和Microsoft Teams进行传播。它冒充PDF文件&#xff0c;利用用户的好奇心诱使其打开&#xff0c;进而下载并执行恶意代码。这种攻击手段使用了Visual Basic for Applications&#xff08;VBA&#xff0…

总结10.15

项目进展 登陆注册&#xff0c;连接了数据库&#xff0c;找回密码写到了通过给邮箱发送验证码&#xff0c;然后重新输入密码 项目看法 之后俩天加紧把这个登陆注册这些搞完&#xff0c;注册用到的随机生成一个账号且不重复&#xff0c;且设置一个邮箱作为之后找回密码时候的…

realman——基于SDK的pick_and_place

文章目录 概要手眼标定外参发布采摘流程核心代码设定初始位置设定安放位置坐标变换单次采摘和安放预采摘点的计算预采摘点和采摘点的运动控制参考概要 这篇博客主要介绍用官方SDK来实现睿尔曼机械臂的运动控制(从采摘到安放),对于如何获取采摘点的三维坐标不做描述。 PS:m…

Vue-3.3ESLint

ESLint代码规范 代码规范&#xff1a;一套写代码的约定规则。 JavaScript Standard Style规范说明https://standardjs.com/rules-zhcn.html 代码规范错误 如果你的代码不符合standard的要求&#xff0c;ESlint会跳出来提醒。 比如&#xff1a;在mian.js中随意做一些改动&a…

【AI视野·今日Sound 声学论文速览 第二十三期】Wed, 11 Oct 2023

AI视野今日CS.Sound 声学论文速览 Wed, 11 Oct 2023 Totally 14 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Sound Papers AutoCycle-VC: Towards Bottleneck-Independent Zero-Shot Cross-Lingual Voice Conversion Authors Haeyun Choi, Jio Gim, Yuho Lee, Y…