方法是一块具有名称的代码。
方法头+方法体
方法头:指定方法的特征,返回类型,方法名称
方法体:可执行代码的语句序列
方法体是一个块,是大括号括括起来的语句序列。
**包含:**局部变量,控制流结构,方法调用,内嵌的块,其它方法(局部函数)
局部变量经常用于保存局部的或临时的数据。
字段通常是保存和对象状态有关的数据。
声明一个局部变量:
Type Identifier = Value;( 类型 变量名称,可选的初始化语句)
局部变量的生存周期仅限于创建它的块及其内嵌的块。
在方法体内任意位置声明局部变量,但必须使用它们门前声明。
类型推断和var关键字
var关键字不是表示特殊变量,只是语法速记,表示任何从初始化语句右边推断出的类型。
使用var关键字的条件:
只能用于局部变量,不能用于字段
只能在变量声明中包含初始化时使用
一旦编译器推断出变量的类型,它就是固定不能更改的。
var关键字并不改变C#的强类型性质。
嵌套块中的局部变量
方法体内部可以嵌套其它的块:
可以有任意数量的块
局部变量可以在嵌套块的内部声明
一旦被初始化,值就不能改变
主要特征:在声明时必须初始化;在声明后不能被改变
const Type Indetifier = Value;
类型前使用关键字const,是核心声明的一部分,必须在类型前面
必须有初始化语句
例如:const double PI=3.1415;
控制流指的是程序从头到尾的执行流程。控制流语句允许你改变执行的顺序。
选择语句:if, if…else…, switch
迭代语句:for , while, do, foreach
跳转语句:break, continute, goto, return
break 跳出当前循环
continute 结束本次循环,执行下一个循环
goto 跳到一个命名的语句
return 返回到调用方法继续执行
从方法体的内部调用其它方法。
static int sum(int a, int b)
{
return a + b;
}
static void Main(string[] args)
{
int a_and_b = sum(3, 4);// 调用sum( )方法
Console.WriteLine(a_and_b);
}
方法可以返回一个值,返回值被插入到调用代码中发起调用的表达式所在位置。
不返回值得方法声明为void,有返回值得函数必须有return语句。
上面示例方法sum()方法2个整形输入参数的和。
任何时候可以不带参数的return语句退出方法
从C# 7.0开始,可以在一个方法中声明一个独立的方法
static void MethodWithLocalFunction()
{
int MyLocalFucntion(int x)//局部函数
{
return x * x;
}
int result = MyLocalFucntion(4);//调用局部函数
Console.WriteLine($“Result of local function call:{result}”);
}
形参
形参是局部变量,它声明在方法的参数列表中,不是在方法体中。
形参是变量,有类型和名称
和方法中的局部变量不同,参数在方法体外面定义,并且在方法开始之前初始化
参数列表中可以有任意数目的的形参声明,且必须逗号分割
上示例sum(int a,int b)中int a,int b 即声明的形参
实参
当调用一个方法时,形参的值必须在代码执行前初始化。用于初始化形参的的表达式或表变量称为实参(actualparameter, argument)
实参必须与对应的形参的类型匹配
调用时传入的值为实参 sum(3,4),其中的实参即对应的位置的3,4
位置参数:实参数量和形参数量一致,且实参类型和形参类型一致
方法被调用时,执行如下操作:
在栈中为形参分配空间
将实参的值分复制给形参
使用引用参数时必须在方法的声明和调用中都使用ref修饰符
实参必须是变量,在做实参时必须赋值。ref
将引用类型对象做为值参数传递
将引用类型对象作为引用参数传递
class MyDemo
{
public int demoValue = 21;
}
static void MyMethod(ref MyDemo d1, ref int d2)
{
d1.demoValue = d1.demoValue + 5;
d2 = d2 + 5;
Console.WriteLine($“d1.demoValue:{d1.demoValue}, d2:{d2}”);
}
static void Main(string[] args)
{
MyDemo demo = new MyDemo();
int x = 10;
MyMethod(ref demo, ref x);//调用方法
Console.WriteLine($“demo.demoValue:{demo.demoValue}, x:{x}”);
}
输出:
d1.demoValue:26, d2:15
demo.demoValue:26, x:15
实参和形参指向堆中相同的对象。
输出参数用于从方法体内把数据传参到调用代码,行为与引用参数类似。
必须在声明和调用中使用修饰符out
C# 7.0开始,不要预先声明一个变量做out 参数。
新语法:消除显示的变量声明,直接在方法调用时加入变量类型声明
参数数组允许特定类型的0个或多个实参对应一个特定的形参。这样就是可变参数了,参数数量可变。
在一个参数列表中只能由一个参数数组
如果有,则必须是列表中的最后一个
由参数数组表示的所以参数必须是同一个类型
使用params修饰符
数据类型后放置一组空的方括号
params Type[] 参数数组名称
方法的调用
延伸式:调用中使用独立的实参
将数组作为实参
static int Get_Sum(params int[] x)
{
int total = 0;
foreach (var item in x)
{
total = total + item;
}
return total;
}
测试:
Console.WriteLine(Get_Sum(1,2,3));
Console.WriteLine(Get_Sum(1, 2, 3,4,5));
可以输入任意个实参
17. ref局部变量和ref 返回
一个类中可以有多个同名方法,这叫做方法重载method overloading
使用相同名称的每个方法必须有一个和其它方法不同的签名
方法的签名由以下信息组成:
方法的名称
参数的数目
参数的数据类和顺序
参数修饰符
注意:
返回类型不签名的一部分
形参的名称也不是签名的一部分
前面所讲的都是位置参数,实参位置都必须与形参位置对应。
C#还允许使用命名参数,只要显示指定参数的名字,就可以以任意顺序在方法中调用。
可同时使用位置参数和命名参数,但是位置参数必须先列出。
Optional parameter可选参数,调用时可以包含这个参数,也可以省略
局部变量和参数都是位于栈上的。
调用方法时,内存从栈的顶部开始分配,保存和方法关联的一些数据项,这块内存叫做方法的栈帧-stack frame.
栈帧包含内容如下:
返回的地址,也就是在方法退出时候继续执行的位置。
分配内存的参数,也就是方法的值参数,还可能是参数数组。
和方法调用相关的其它管理数据。
方法调用时,整个栈帧都会压入栈,在方法退出时,整改栈帧都会从栈上弹出。弹出栈帧也叫做栈展开。
方法调用自身,这叫做递归。