深入探索方法调用与类成员机制
立即解锁
发布时间: 2025-08-21 00:06:04 阅读量: 3 订阅数: 8 


C#编程基础与实战技巧
### 深入探索方法调用与类成员机制
#### 1. 栈帧的奥秘
我们都知道,局部变量和参数通常存储在栈上。当调用一个方法时,会在栈顶分配一块内存,用于存放与该方法相关的多个数据项,这块内存就被称为该方法的栈帧。
栈帧包含以下内容:
- 返回地址:即方法退出后恢复执行的位置。
- 分配内存的参数:包括方法的值参数,若有参数数组也在此列。
- 与方法调用相关的其他管理数据项。
当调用方法时,其整个栈帧会被压入栈中;方法退出时,整个栈帧会从栈中弹出,这一过程有时也被称为栈的展开。
以下是一个示例代码,展示了方法调用和栈帧的创建与展开过程:
```csharp
class Program
{
static void MethodA( int par1, int par2)
{
Console.WriteLine("Enter MethodA: {0}, {1}", par1, par2);
MethodB(11, 18); // Call MethodB.
Console.WriteLine("Exit MethodA");
}
static void MethodB(int par1, int par2)
{
Console.WriteLine("Enter MethodB: {0}, {1}", par1, par2);
Console.WriteLine("Exit MethodB");
}
static void Main( )
{
Console.WriteLine("Enter Main");
MethodA( 15, 30); // Call MethodA.
Console.WriteLine("Exit Main");
}
}
```
该代码的输出如下:
```
Enter Main
Enter MethodA: 15, 30
Enter MethodB: 11, 18
Exit MethodB
Exit MethodA
Exit Main
```
#### 2. 递归的魅力
除了调用其他方法,方法还可以调用自身,这就是递归。递归能够生成非常优雅的代码,例如计算一个数的阶乘的方法:
```csharp
int Factorial(int inValue)
{
if (inValue <= 1)
return inValue;
else
return inValue * Factorial(inValue - 1); // Call Factorial again.
}
```
方法调用自身的机制与调用其他不同方法的机制完全相同。每次调用方法时,都会有一个新的栈帧被压入栈中。
以下是另一个递归示例代码:
```csharp
class Program
{
public void Count(int inVal)
{
if (inVal == 0)
return;
Count(inVal - 1); // Invoke this method again.
Console.WriteLine("{0}", inVal);
}
static void Main()
{
Program pr = new Program();
pr.Count(3);
}
}
```
该代码的输出为:
```
1
2
3
```
#### 3. 类成员的多样性
之前我们已经了解了类成员中的字段和方法,接下来将介绍更多类型的类成员及其特性。
类成员类型如下表所示:
| 数据成员(存储数据) | 函数成员(执行代码) |
| ---- | ---- |
| ♦ 字段 | ♦ 方法 |
| 常量 | 属性 |
| | 构造函数 |
| | 析构函数 |
| | 运算符 |
| | 索引器 |
| 事件 | |
#### 4. 成员修饰符的顺序
字段和方法的声明可以包含如`public`和`private`等修饰符。类成员声明语句由核心声明、可选的修饰符集和可选的属性集组成,其语法结构如下:
```
[ attributes ] [ modifiers ] CoreDeclaration
```
可选组件的规则如下:
- 修饰符:若有修饰符,必须放在核心声明之前;若有多个修饰符,顺序可以任意。
- 属性:若有属性,必须放在修饰符和核心声明之前;若有多个属性,顺序也可以任意。
例如,`public`和`static`这两个修饰符可以一起使用来修饰某些声明,它们的顺序可以互换,以下两行代码语义相同:
```csharp
public static int MaxVal;
static public int MaxVal;
```
#### 5. 实例类成员
类成员可以与类的实例相关联,也可以与整个类相关联。默认情况下,成员与实例相关联,每个类的实例都有自己的类成员副本,这些成员称为实例成员。
以下是一个示例代码,展示了实例成员的特性:
```csharp
class D
{
public int Mem1;
}
class Program
{
static void Main()
{
D d1 = new D();
D d2 = new D();
d1.Mem1 = 10; d2.Mem1 = 28;
Console.WriteLine("d1 = {0}, d2 = {1}", d1.Mem1, d2.Mem1);
}
}
```
该代码的输出为:
```
d1 = 10, d2 = 28
```
#### 6. 静态字段
除了实例字段,类还可以有静态字段。静态字段由类的所有实例共享,所有实例都访问同一个内存位置。因此,如果一个实例更改了该内存位置的值,所有实例都能看到这个更改。
使用`static`修饰符来声明静态字段,示例如下:
```csharp
class D
{
int Mem1; // Instance field
static int Mem2; // Static field
}
```
从类外部访问静态成员也使用点语法,但由于没有实例,必须使用类名,例如:
```csharp
D.Mem2 = 5; // Accessing the static class member
```
以下是一个包含静态字段的完整示例代码:
```csharp
class D {
int Mem1;
static int Mem2;
public void SetVars(int v1, int v2) // Set the values
{ Mem1 = v1; Mem2 = v2; }
public void Display( string str )
{ Console.WriteLine("{0}: Mem1= {1}, Mem2= {2}", str, Mem1, Mem2); }
}
class Program {
static void Main()
{
D d1
```
0
0
复制全文
相关推荐










