本章内容:
方法的结构
方法体内部的代码执行
局部变量
局部常量
控制流
方法调用
返回值
返回语句和void方法
局部函数
参数
值参数
引用参数
引用类型作为值参数和引用参数
输出参数
参数数组
参数类型总结
方法重载
命名参数
可选参数
栈帧
递归
方法重载
一个类中可以有多个同名方法,这叫作方法重载(methodoverloading)。使用相同名称的
每个方法必须有一个和其他方法不同的签名()。
- 方法的签名由下列信息组成,它们在方法声明的方法头中:
- 方法的名称;
- 参数的数目;
- 参数的数据类型和顺序;
- 参数修饰符。
- 返回类型不是签名的一部分,而我们往往误认为它是签名的一部分。
- 请注意,形参的名称也不是签名的一部分。
例如,下面4个方法是方法名AddValues的重载:
class A
{
long AddValues(int a,int b)
{
return a+b;
}
long AddValues(int c,int d,int e){return c+d+3;}
long AddValues(float f,float g){return (long)(f+g);}
long AddValues(long h,long m){return h+m;}
}
下面的代码展示了一个非法的方法重载。两个方法仅返回类型和形参名不同,但它们仍有相
同的签名,因为它们的方法名相同,而且参数的数目、类型和顺序也相同。编译器会对这段代码
生成一条错误消息。
命名参数
至此我们用到的所有参数都是位置参数,也就是说每一个实参的位置都必须与相应的形参位
置对应。
此外,C#还允许我们使用命名参数(named parameter)。只要显式指定参数的名字,就可以
以任意顺序在方法调用中列出实参。细节如下。
- 方法的声明没有什么不一样。形参已经有名字了。
- 不过在调用方法的时候,形参的名字后面跟着冒号和实际的参数值或表达式,如下面的
方法调用所示。在这里a、b、c是Calc方法3个形参的名字。
图6-13演示了使用命名参数的结构。
在调用的时候,你可以同时使用位置参数和命名参数,但所有位置参数必须先列出。例如,
下面的代码演示了Calc方法的声明及其使用位置参数和命名参数不同组合的5种调用方式。
class MyClass
{
public int Calc(int a,int b,int c)
{
return (a+b)**c;
}
static void Main()
{
MyClass mc=new MyClass();
int r0=mc.Calc(4,3,2); //位置参数
int r1=mc.Calc(4,b:3,3,c:2); //位置参数和命名参数
int r2=mc.Calc(4,c:2,b:3); //交换了顺序
int r3=mc.Calc(c:2,b:3,a:4); //所有都是命名参数
int r4=mc.Calc(c:2,b:1+2,a:3+1);//命名参数表达式
Console.WriteLine($"{r0},{r1},{r3},{r4}");
}
}
命名参数对于自描述的程序来说很有用,因为我们可以在方法调用的时候显示哪个值赋给哪
个形参。例如,如下代码调用了两次GetCylinderVolume,第二次调用具有更多的信息并且更不
容易出错。
class MyClass
{
double GetCylinderVolume(double radius,double height)
{
return 3.1415*radius*radius*height;
}
static void Main(string[] args)
{
MyClass mc=new MyClass();
double volume;
volume=mc.GetCylinderVolume(3.0,4.0);
volume=mc.GetCylinderVolume(radius:3.0,height:4.0);
}
}