方法体是一个块,可以包含以下内容:
使用 var 关键字可以进行类型推断,而不需要明确指定变量类型。var 关键字并不改变 C# 的强类型性质。
在 C# 中不论嵌套级别如何,都不能在第一个名称的有效范围内声明另一个同名的局部变量。
和局部变量一样,局部常量声明在方法体或代码块里,并在声明它的块结束的地方失效。
注意:const 不是修饰符,而是核心声明的一部分。
C# 7.0 开始,可以在一个方法中声明另一个单独的方法,称为局部函数。
使用值参数时,会发生如下操作:
方法使用值参数不能改变原始的值类型数据,但是可以改变引用类型的数据:
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); // 实参
}
}
引用参数具有如下特征:
对于引用类型对象:
将引用类型对象作为引用参数传递,目的是改变引用对象;
如果仅需改变引用类型对象的内容,只需值参数传递即可。
与 ref 不同,out 有如下要求:
C# 7.0 后,可以对输出参数进行简化声明,不需要预先声明一个变量来用作 out 参数了。如图 6.9 所示,声明后的 a1 和 a2 可以在方法调用结束后继续使用。
可以使用两种方式为参数数组提供实参:
ListInts(10, 20, 30); // 3 个 int
int[] intArray = {1, 2, 3};
ListInts(intArray);
注意:在调用时不使用 params 修饰符。
使用独立实参调用时,编译器将执行以下步骤:
void ListInts(params int[] inVals) { ... } // 方法声明
...
ListInts(); // 0 个实参
ListInts(1, 2, 3); // 3 个实参
ListInts(4, 5, 6, 7, 8); // 5 个实参
当数组 inVals
在堆中被创建时,实参的值被赋值到数组中,因此可看做值参数:
编译器将使用传入的数组而不是重新创建一个。
创建别名的语法需要使用 ref 两次。
ref 返回使得方法可以返回引用而不是值,同样也需要使用两次 ref:
有关 ref 的使用有如下注意事项:
使用相同名称的方法必须和其他同名方法有不同的签名,签名由如下信息组成:
返回类型和形参名称都不是签名的一部分。
C# 可以使用命名参数,显示指定参数的名称,就能够以任意顺序在方法中列出实参。
可以同时使用位置参数和命名参数,但所有位置参数必须先列出。
可选参数能够设置参数的默认值,图 6.18 列出了哪些时候能使用可选参数。
所有必填参数需放在可选参数声明之前,params 参数放在可选参数之后,如图 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(); // 使用两个默认值
}
}
调用方法时,内存从栈的顶部开始分配,保存和方法关联的一些数据项。这块内存称为方法的栈帧。