概 念:
将一块复杂的代码或可能重复利用的代码单独的封装起来,就称之为函数。
在哪里需要使用这段代码就在哪里调用对应的函数即可。
优 点:
- 可以使代码更加简洁
- 可以提高代码的复用度
- 可以提高代码的可维护性
样 式:
修饰符 返回值类型 函数名称(参数列表)
{
方法体
}
函数名称规范:各个单词首字母均大写,其余字母小写
函数必须声明实现在类型内部,其他函数外部
- 各个函数之间相互独立,不能包含或被包含
一、无返回值函数
样 式:
static void 函数名称( )
{
方法体
}
void不是有效数据类型,不能声明变量存放数据。只能用于函数返回值位置,表示无任何数据返回。
空( ):表示当前函数无参数,但是()不可以省略。
普通函数必须有方法体,即函数实现。参数列表之后跟随{ }就是函数实现,即使{ }中什么都不写,也相当于实现了函数。不可以访问调用没有实现的函数。
当程序启动后,系统只会默认调起main函数,其他函数需要程序员主动调起。
- 函数未被调用时,没有任何实际意义,也不会占用内存空间。
static void Print()
{
Test();
//Print();
Console.WriteLine("=================================");
for (int i = 0; i < 5; i++)
{
Console.WriteLine("hello world");
}
Console.WriteLine("=================================");
}
static void Test()
{
Console.WriteLine("*************************");
}
static void Main(string[] args)
{
Print();
Test();
Console.WriteLine("O(∩_∩)O哈哈~");
Console.ReadKey();
}
程序的运行:实际上就是任意多个函数的调用和调用完成
- main函数中可以调用其他函数
- 其他函数中也可以调用其他函数
- 函数也可以直接或间接的调用自身,但必须要处理终止,否在会导致崩溃
- 不建议调用main函数,因为main函数影响程序周期
调用函数:函数名称(参数列表) 若无参就跟随空(),括号不可以省略
- 函数名称是函数位置入口,通过调用函数,进入到函数内部执行操作。
- 需要在哪里使用在函数中包含的代码,就在哪里调用函数,可以调用任意多次。
- 函数在被调用时会入栈,调用完成时会出栈。
- 被某个函数占用的栈空间称之为栈帧,栈帧中存放调用函数位置的记录、形参以及函数中声明的变量。
- 栈空间遵从先进后出的原则,越先进来的越后出去。
二、有返回值函数
使用场景:
当调用该函数的位置可能需要获取该函数内部的数据值,那此时就可以通过返回值的形式,在函数执行完成时,将数据返回到调用函数的位置。
样式:
static 有效的数据类型作为返回值类型 函数名称(参数列表)
{
方法体
}
static int Calculate()
{
int mul = 1;
for (int i = 2; i <= 5; i++)
{
mul *= i;
}
Console.WriteLine("5的阶乘为{0}。", mul);
//有返回值的函数,必须在任何情况下,都有具体数据返回
//通过return关键字,跟随表达式。返回的是表达式的值
return mul;
//当函数遇到一个return时,即终止操作,退出函数。其下的代码将无法再执行
Console.WriteLine("========================");
}
static void Main(string[] args)
{
//可以选择是否接收操作函数的返回值,并不是有返回值就一定要使用处理返回值
Calculate();
//接收使用返回值的方式:
//1、通过与返回值类型相同的变量接收返回值
//将赋值运算符右侧有返回值函数的返回值赋值给左侧的变量
int num = Calculate();
Console.WriteLine("num:{0}", num);
//2、可以直接使用操作函数的返回值。因为有返回值函数调用携带值
Console.WriteLine("阶乘为{0}", Calculate());
Console.ReadKey();
}
三、有参函数
- 当函数内部需要获取操作函数外部的数据或变量时,就需要进行传参操作,就需要参数。
形 参:
- 若函数内部需要使用函数外部的数据,就要在参数列表中声明参数变量,这个变量就被称为形参。
- 形参的作用域在函数内部,但是可以在函数调用时接收外部数据。
- 各个参数通过逗号隔开。形参列表中实际就是任意多个变量的声明
形参种类:
可选形参:
- 做了初始化的形参变量就称为可选形参,可选形参必须在全部必需形参的后面
- 可以选择是否对可选形参传参,若不传参则使用可选形参的初始值,若传参则相当于重新赋值,使用传递给它的实参数据。
必需形参:
- 只有声明没有初始化的形参就称为必需形参
- 必须要对必需形参进行传参操作
//声明带参函数:函数名称(形参列表)
static void PrintN(string constant, int n = 3)
{
for (int i = 0; i < n; i++)
{
Console.WriteLine(constant);
}
}
static void Main(string[] args)
{
//调用带参函数:函数名称(实参列表)
//传参:调用函数时,通过实参给形参赋值的过程
PrintN("hello");
int count = 5;
PrintN("hello world", 5);
Console.ReadKey();
}
四、重载函数
当多个函数进行相似的功能处理,且具备不同的参数列表时,这些函数就可以同名,这些函数就称为重载函数。
参数列表不同是指:参数类型不同或者参数个数不同。
声明在同一个类型内部的各个函数,必须具备不同的函数签名。
函数签名包括:
* 函数名称
* 参数列表:参数类型 参数个数
* 当具有多个不同类型的参数时,参数的顺序也是签名的一部分函数返回值类型和参数名称不属于函数签名,无法影响两个函数是否不同。
static int Add(int n1, int n2)
{
Console.WriteLine("=========================");
return n1 + n2;
}
static double Add(double n1, double n2)
{
Console.WriteLine("***************************");
return n1 + n2;
}
static int Add(int n1, int n2, int n3)
{
Console.WriteLine("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&");
return n1 + n2 + n3;
}
static float Add(float n1, float n2)
{
Console.WriteLine("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$");
return n1 + n2;
}
static void Main(string[] args)
{
//当存在多个重载函数时,系统会自动根据实参调起最合理的函数
Add(1, 13, 12);
Console.ReadKey();
}
五、递归函数
定义:一个函数直接或间接的调用自身,这个函数就称为递归函数。
注意:递归函数必须要有终止条件,且要在递归过程中逐渐靠近最终的结果。
使用场景:通常能用循环解决的问题都可以使用递归解决,一个递归函数可以取替一层循环
优点: 使代码更加简洁
缺点:
* 逻辑比较复杂
* 多个递归函数嵌套或者递归次数过多,会导致函数频繁入栈,增加消耗降低效率。声明步骤:
* 1、找出递归的终止条件
* 2、找出相邻两次函数调用的关联
* 3、将上面两步转换为代码操作
//计算n的阶乘
static ulong Calculate(uint n)
{
if (n == 1)
{
//1的阶乘直接返回1.终止条件
return 1;
}
//处理相邻两次函数调用的关系
return n * Calculate(n - 1);
}
static void Main(string[] args)
{
Console.WriteLine(Calculate(5));
Console.ReadKey();
}