首页 > 其他分享 >3 栈帧 递归 类成员 静态字段 常量 静态函数 属性 构造函数 析构函数 this readonly 索引器 分部方法 分部类

3 栈帧 递归 类成员 静态字段 常量 静态函数 属性 构造函数 析构函数 this readonly 索引器 分部方法 分部类

时间:2022-10-29 00:14:08浏览次数:63  
标签:函数 静态 成员 修饰符 实例 声明 构造函数

好记性不如烂笔头

目录

栈帧

​ 现在,我们已经知道了 本地变量(局部变量),参数都存放在栈上,现在我们研究下其组织。

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

  • 栈帧包含的内存保存如下内容
    • 返回地址,也就是在方法退出的时候继续执行的位置。
    • 这些参数分配的内存,也就是方法的值参数,或者还可能是参数数组(如果有的话);
    • 各种和方法调用相关的其他管理数据项
  • 在方法调用是,整个栈帧会压入栈。
  • 在方法退出的时候,整个栈帧都会从栈上弹出。弹出的栈帧有的时候也叫做栈展开(unwind);
static void MethodA(int a,int b)
{
    Console.WriteLine("Enter MethodA: {0} {1}",a,b);
    MethodB(12,10);
    Console.WriteLine("End MethodA");
}

static void MethodB(int a,int b)
{
    Console.WriteLine("Enter MethodB: {0} {1}",a,b);
    Console.WriteLine("End MethodB");
}
static void Main(string[] args)
{
    MethodA(12, 24);
    Console.ReadKey();
}

输出如下:

Enter MethodA: 12 24
Enter MethodB: 12 10
End MethodB
End MethodA

下图演示了调用方法是栈帧压入栈 和 弹出的过程。

image-20221002004937366

递归

除了调用其他方法,方法也可以调用自身。这叫递归

递归必须有结束条件,不然就一直递归下去了

public static int 递归方法(int value)
{

    if (value <= 1)
    {
        return value;
    }
    return value * 递归方法(value-1);

}

递归方法(5);  // 120
5 * (4*(3*(2))) = 120;

调用方法自身的机制和调用其他方法都是完全一样的,都是每一次调用方法把新的栈帧压入栈顶

public static void 递归方法2(int value)
{
    if (value == 0) return;
    递归方法2(value - 1);
    Console.WriteLine("{0}",value);
}

输出:

1
2
3
4
5

原理:

image-20221002011324930

=深入了解类==

1 类成员

数据成员 函数成员(执行代码)
字段 方法
常量 属性
构造函数
析构函数
运算符
索引
事件

2 成员修饰符的顺序

​ 学习过程中,我们看到字段和方法的声明可以包括 public private 这样的修饰符。多个修饰符可以在一起使用,自然产生了一个问题:他们需要按什么顺序排列?

​ 类成员声明语句由下列部分组成: 核心声明,一组可选的修饰符 和 一组可选的特性(attribute)。用于描述这个结构的语句如下。方括号表示可以选择的。

[特性] [修饰符] 核心声明
  • 修饰符
    • 如果有多修饰符,必须放在核心声明之前。
    • 如果有多个修饰符,可以是任意顺序的
  • 特性
    • 如果有特性,必须放在修饰符前和核心声明前
    • 如果有多个特性,可以是任意顺序的

image-20221002015244391

3 静态字段

静态字段被类的所有实例共享,所有的实例都访问同一块内存位置。因此,如果改内存位置的值被一个实例改变,这种改变对所有实例都可见。

可以用static修饰符将字段声明为静态,如

class D
{
    int Number; // 实例字段
    static int Number2; // 静态字段
}

image-20221002015636142

4 从类的外部访问静态成员

类名.静态字段 = 5;   // 访问静态类成员

4.1 静态成员的生存期

  • 之前我们已经看到了,只有在实例创建之后才能产生实例成员,在实例销毁之后实例成员也就不在了
  • 但是即使类没有实例,也存在静态成员,并且可以访问

5 静态函数成员

  • 同静态字段一样,独立于任何类的实例,没有实例也可以调用
  • 静态函数不能访问实例成员,但是能访问其他静态成员
class A
{
    public static void Func()
    {
        // ...
	}
}

调用方法于静态成员一样

6 其他静态成员类型

数据成员 函数成员
字段 方法
类型 属性
构造函数
运算符
事件

7 成员常量

只能在类中声明而不是方法

class MyClass
{
    const int IntVal = 100;  // 无法赋值,必须初始化
}

8 常量与静态量

成员产品比本地常量更有趣,因为他们表现得和像静态值。他们对每个实例都是可见的,没有实例也可以使用。与真正的静态量不同,常量没有自己的存储位置,而是在编译阶段被编译器做了替换

class A
{
 	public const double PI = 3.14159;
}

class Program
{
    static void Main()
    {
        A.PI; // 3.14159
	}
}
static const double PI = 3.14159; // 错误,不能将常量声明为static

9 属性

与字段类似,属性有如下特征

  • 他有类型
  • 他可以被赋值和读取
    • 然而他和字段不同,属性1是一个函数成员
  • 它不为数据存储分配内存!
  • 它执行代码
    • 属性是指的一组有两个匹配的,称为访问器的方法。
  • set访问器为属性的赋值
  • get访问器为属性的取值
int MyValue
{
    set
	{
    	// ..    
    }
    
    get
    {
        // ..
    }
}

9.1 属性声明和访问器

  • set访问器总是:
    • 拥有一个单独的,隐示的值参,名称为value,与属性的类型相同;
    • 拥有一个返回类型void
  • get访问器总是:
    • 没有值参
    • 拥有一个属性类型一样的返回类型

image-20221002022332975

9.2 只读和只写属性

  • 只有get 是只读 无法写入
  • 只有set 是只写 无法读取

9.3 静态属性

  • 不能访问类的实例
  • 不管类是否有实例,他们都是存在的
  • 当从类的外部访问,必须使用类名引用,而不是实例名

10 实例构造函数

  • 构造函数用于初始化类实例的状态
  • 如果希望能从类的外部创建类的实例,需要将构造函数声明为public
  • 构造函数名与类名一样
  • 构造函数不能有返回值
  • 构造函数可以重载
class A{
    public void A(){
		// ... 
    }
}

10.1 默认构造函数

​ 如果在类的声明中没有显示的声明构造函数,编译器会提供一个隐式的构造函数,他有以下特征:

  • 没有参数

  • 方法体为空

    如果你声明了构造函数,那么编译器就不会设置默认的构造函数

10.2 静态构造函数

​ 构造函数也可以声明为static。通常,静态构造函数用于初始化类的静态字段

  • 初始化类级别的项
    • 在引用任何静态成员之前
    • 在创建累的任何实例之前
  • 类只能有一个静态函数,而且不能带参数。
  • 静态构造函数不能有访问修饰符

11 析构函数

执行在类的实例被销毁之前需要的清理或释放非托管资源的行为

非托管资源 pass....

12 readonly修饰符

​ 字段可以用readonly修饰符声明。其作用类似于将字段声明为const

  • const字段只能在字段的声明语句中初始化,而readonly字段可以在下列任意为设置他的值
    • 字段声明语言,类似const
  • readonly字段的值可以在运行时决定、

13 this关键字

​ this关键字在类中使用,是对当前实例的引用。他只能用在下列类成员的代码块中。

  • 实例构造函数
  • 实例方法
  • 属性和索引器的实例访问器

14 索引器

14.1 什么是索引器

image-20221002230237473

14.2 声明索引器

  • 索引器没有名称。在名称的位置是关键字this。
  • 参数列表在方括号中间。
  • 参数列表中必须至少声明一个参数

image-20221002230405397

image-20221002230412841

14.3 索引器的set访问器

  • 一个隐示参数,名称为value,value持有要保存的数据;
  • 一个或跟多索引参数,表示数据应该保存到哪里。
  • 他的返回值类型为void

image-20221002230650503

14.4 索引器的get访问器

  • 他的参数列表和索引器的声明中的相同
  • 他的返回值类型与索引器相同类型

image-20221002230813976

索引器可以重载 多个参数

image-20221002230930451

15 访问器的访问修饰符

image-20221002231323351

image-20221002231335212

16 分布类 和分布类型

类的声明可以分割成就几个分部类的声明

  • 每个分部类的声明都含有一些类成员的声明
  • 累的分部类声明可以在同一文件中也可以在不同文件中

每个局部声明必须标为 partial class, 而不是单独的关键字class。分部类声明扛起来和普通类相同,除了附加的类型修饰符 partial

image-20221002231733981

类型修饰符partial不是关键字,所以在器他上下文中,可以在程序把他用作标识符。但是之间用在关键字class,struct或interface之前时,他表示分部类型。

17 分部方法

  • 定义分部方法声明
    • 给出签名和返回值类型
    • 声明的实现部分只是一个分号。
  • 实现分部方法声明
    • 给出标签名和返回值类型
    • 正常书写代码块语句
  • 定义声明和实现声明的签名和返回类型必须匹配。签名和返回类型有如下特征:
    • 返回值必须是void
    • 签名不能包括访问修饰符,这使分部方法是隐示私有的
    • 参数列表补鞥呢包含out参数。

image-20221002232616388

标签:函数,静态,成员,修饰符,实例,声明,构造函数
From: https://www.cnblogs.com/lddragon1/p/16837880.html

相关文章

  • 5 访问修饰符 抽象类 抽象成员 密封类 静态类 扩展方法 命名约定
    目录访问修饰符抽象成员抽象类密封类静态类扩展方法命名约定访问修饰符所有声明在类中的成员都是可见的,无论他们的访问性如何。继承的成员对派生的成员可以是可见的,也......
  • 函数的防抖与节流实现
    一、什么是节流函数,什么是防抖函数,它们之间的区别是什么?·节流函数:节流,可以理解为节省流量。当一个请求被用户在短时间内不停点击时(用户频繁发送一个数据请求),为了减轻服务......
  • 一文带你了解Java中的Scanner键盘输入关键字、random 随机数关键字、System类和匿名函
    Scanner键盘输入Scanner类的功能:可以实现键盘输入数据,到程序当中。引用类型的一般使用步骤:1.导包import包路径.包名称如果需要使用目标类,和当前类位于同一个包下,......
  • 【笔记05】Javascript - 基本概念 - (函数递归)
    先看一个试题: 求n的阶乘通常,我们会写:functionfac(num){varres=1;for(vari=1;i<=num;i++){res*=i;}returnres;}观察阶乘可以发现两个特点:特点一:......
  • Matlab 之 find()函数
    Matlab之find()函数 当我第一次用matlab语言编写一个工程项目时,发现自己编写的脚本里循环特别多,导致编程效率很低,这让我特别苦恼。有一次导师让我阅读他编写的......
  • 【CFgym102482D】Gem Island(生成函数)
    题意:有一个序列\(a_1,\cdots,a_n\),初始时它们全为\(1\)。进行\(d\)轮操作:每轮操作以正比于\(a\)的概率选择一个\(a_i\)加\(1\)。求最后\(a_1,\cdots,a_n\)中前......
  • Javascrip内置函数--计时器
    延时执行:setTimeout()  setTimeout的三种写法:console.log(1);/***第一个参数是代码,注意代码需用引号包裹,否则会立即执行代码*第二个参数是1000,即1000ms......
  • 【bzoj4869】【六省联考2017】相逢是问候(扩展欧拉函数)
    和《花神游历各国》有异曲同工之妙。首先能想到扩展欧拉定理:\[a^b\equiv\begin{cases}a^{b\bmod\varphi(p)+\varphi(p)}&\text{if}b\geq\varphi(p)\\a^b&\text{if}......
  • vue 中watch 回调函数和methos中方法的区别
    1.vue中代码<el-inputv-model="searchkey"placeholder="键名"@input="handleInput"clearablestyle="max-width:300px;"></el-/utils/commonwen文件加下export......
  • 常用的Python函数有几类
    今天就给大家介绍12类,新手在做写代码的时候容易卡壳,尤其当接触的函数以及其他知识比较多的时候,经常会看完需求之后不知道自己该用什么方法来实现它,实现的逻辑可能你有,但怎么......