函数(方法)
本质是一块具有名称的代码块
可以使用函数(方法)的名称来执行该代码块
函数(方法)是封装代码进行重复使用的一种机制
函数(方法)的主要作用
1.封装代码
2.提开代码复用率(少写点代码)
3.抽象行为
右键->转到定义(F12),可以跳转到函数定义里
1.class语句块中
2.struct语句块中
1 2 3 4
static 返回类型 函数名(参数类型参数名1,参数类型参数名2,.......)
{
函数的代码逻辑;
函数的代码逻辑;
函数的代码逻辑;
.........;
5
return返回值;(如果有返回类型才返回)
}
1. 关于static 不是必须的 在没有学习类和结构体之前 都是必须写的
2-1.关于返回类型 引出一个新的关键字 void(表示没有返回值)
2-2.返回类型 可以写任意的变量类型 14种变量类型+复杂数据类型(数组、枚举、结构体、类class)
3. 关于函数名 使用帕斯卡命名法 命名myName(驼峰命名法) MlyName(帕斯卡命名法)
4-1. 参数不是必须的 可以有0~n个参数 参数的类型也是可以是任意类型的 14种变量类型+复杂数据类型(数组、枚举、结构体、类class)
多个参数的时候 需要用逗号隔开
4-2. 参数名 用驼峰命名法
5. 当返回值类型不为void时 必须通过新的关键词 return返回对应类型的内容(注意:即使是void也可以选择性使用return)
1.无参无返回值函数
//定义函数
static void SayHello()
{
Console.WriteLine("Hello Word");
//在没有返回值时也就是返回值类型是void可以省路
//return;
}
static void Main(string[] args)
{
//使用函数
SayHello();
}
2.有参无返回值函数
//定义函数
static void SayYourName(string name)
{
Console.WriteLine("你的名字是{0}", name);
}
static void Main(string[] args)
{
//使用函数
//参数可以是常量,变量,函数都可以
//参数一定是传一个能得到对应类型的表达式
string str = "Shuai";
SayYourName(str);
SayYourName("Shuai2");
}
3.无参有返回值函数
//定义函数
static void SayYourName(string name)
{
Console.WriteLine("你的名字是{0}", name);
}
static string WhatYourName()
{
return "Shuai";
}
static void Main(string[] args)
{
//使用函数
//传入—个返回值时string的函数
SayYourName(WhatYourName());
//有返回值的函数要不直接拿返回值来用
//要不就是拿变量接收它的结果
string str2 = WhatYourName();
//也可以直接调用但是返回值对我们来说就没用了
WhatYourName();
}
4.有参有返回值函数
//定义函数
static int Sum(int a,int b)
{
//retrun后面可以写一个表达式
//只要这个表达式的结果和返回值类型是一致的就行
return a + b;
}
static void Main(string[] args)
{
Console.WriteLine(Sum(10, 20));
//打印结果:30
}
5.有参有多返回值函数
传入两个数,然后计算两个数的和以及他们两的平均数,得出结果返回出来
//定义函数
//函数的返回值—定是一个类型只能是一个内容
static int[] Calc(int a,int b)
{
int sum = a + b;
int avg = sum / 2;
//如果用数组作为返回值出去,那么前提是使用者知道这个数组的规则
return new int[] {
sum, avg };
}
static void Main(string[] args)
{
//使用函数
int[] arr = Calc(5, 7);
Console.WriteLine(arr[0] +" "+ arr[1]);
//打印结果:12,6
}
即使函数没有返回值我们也可以使用return,
return可以直接不执行之后的代码,直接返回到函数外部
//定义函数
static string Speak(string str)
{
if( str == "混蛋" )
{
return "";
}
return str;
}
static void Main(string[] args)
{
//使用函数
Console.WriteLine(Speak("混蛋"));
//打印结果:
Console.WriteLine(Speak("混蛋123"));
//打印结果: 混蛋123
}
1.练习1
写一个函数,比较两个数字的大小,返回最大值
static int CheckMax(int a,int b)
{
//if (a > b)
// return a;
//return b;
return a > b ? a : b;
}
static void Main(string[] args)
{
Console.WriteLine(CheckMax(3, 6));
//打印结果:6
}
2.练习2
写一个函数,用于计算一个圆的面积和周长,并返回打印
面积:Πr² 周长:2Πr
static float[] CalCirc(float r)
{
//float[] f = new float[2];
//f[0] = 3.14f * r * r;
//f[1] = 2 * 3.14f * r;
//return f;
return new float[] {
3.14f * r * r, 2 * 3.14f * r };
}
static void Main(string[] args)
{
float r = 3.0f;
float[] f = CalCirc(r);
Console.WriteLine("半径{0},面积{1},周长{2}", r, f[0], f[1]);
//打印结果:半径3,面积28.26,周长18.84
}
3.练习3
写一个函数,求一个数组的总和、最大值、最小值、平均值
static void Calc(int[] arr)
{
if(arr.Length==0)
{
Console.WriteLine("数组不能为空");
return;
}
int sum = 0;
float avg = 0;
int max = arr[0];
int min = arr[0];
for (int i = 0; i < arr.Length; i++)
{
sum += arr[i];
if (max < arr[i])
max = arr[i];
if (min > arr[i])
min = arr[i];
}
avg = (float)sum / arr.Length;
Console.WriteLine("最大值{0},最小值{1},总和{2},平均数{3}", max, min, sum, avg);
}
static void Main(string[] args)
{
int[] arr = {
1, 2, 3, 4, 5, 6, 7, 8 };
Calc(arr);
//打印结果:最大值8,最小值1,总和36,平均数4.5
}
4.练习4
写一个函数,判断你传入的参数是不是质数
质数:一个只能被1和自己整除的数
static bool IsPrime(int number)
{
//判断质数的逻辑
for (int i = 2; i < number; i++)
{
//得到从2到 num-1 之间的数
if (number % i == 0)
return false;
}
//默认就认为它是质数
return true;
}
static void Main(string[] args)
{
int number = 5;
Console.WriteLine("{0}{1}质数", number, IsPrime(number) ? "是" : "不是");
//打印结果:5是质数
}
5.练习5
写一个函数,判断你输入的年份是否是闰年
闰年判断条件:
年份能被400整除(2000)
或者
年份能被4整除,但是不能被100整除(2008)
static bool IsLeapYear(int year)
{
if (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0))
{
return true;
}
return false;
}
static void Main(string[] args)
{
int year = 2020;
Console.WriteLine("{0}{1}闰年", year, IsLeapYear(year) ? "是" : "不是");
//打印结果:2020是闰年
}
学习ref和out的原因
它们可以解决 在函数内部改变外部传入的内容 里面变了外面也要变
static void ChangeValue(int value)
{
value = 3;
}
static void Main(string[] args)
{
int a = 1;
ChangeValue(a);
Console.WriteLine(a);
}
//打印结果 :1
如图:
static void ChangeArrayValue(int[] arr)
{
arr[0] = 99;
}
static void Main(string[] args)
{
int[] arr2 = {
1, 2, 3 };
ChangeArrayValue(arr2);
Console.WriteLine(arr2[0]);
}
//打印结果 :99
如图:
static void ChangeArrayValue(int[] arr)
{
arr[0] = 99;
}
static void ChangeArray(int[] arr)
{
arr = new int[] {
10, 20, 30 };
}
static void Main(string[] args)
{
int[] arr2 = {
1, 2, 3 };
ChangeArrayValue(arr2);
Console.WriteLine(arr2[0]);//99
ChangeArray(arr2);
Console.WriteLine(arr2[0]);//99
}
如图:
函数参数的修饰符
当传入的值类型参数在内部修改时或者引用类型参数在内部重新申明时
外部的值会发生变化
1.ref使用
static void ChangeValueRef(ref int value)
{
value = 3;
}
static void ChangeArrayRef(ref int[] arr)
{
arr = new int[] {
100, 200, 300 };
}
static void Main(string[] args)
{
int a = 1;
ChangeValueRef(ref a);
Console.WriteLine(a);
//打印结果:3
int[] arr2 = {
1, 2, 3 };
ChangeArrayRef(ref arr2);
Console.WriteLine(arr2[0]);
//打印结果:100
}
2.out使用
static void ChangeValueOut(out int value)
{
value = 99;
}
static void ChangeArrayOut(out int[] arr)
{
arr = new int[] {
666, 777, 888 };
}
static void Main(string[] args)
{
int a = 1;
ChangeValueOut(out a);
Console.WriteLine(a);
//打印结果:99
int[] arr2 = new int[] {
1, 2, 3 };
ChangeArrayOut(out arr2);
Console.WriteLine(arr2[0]);
//打印结果:666
}
1.ref传入的变量必须初始化 out不用
2.out传入的变量必须在内部赋值 ref不用
1.ref传入的变量必须初始化,out不用
static void ChangeValueOut(out int value)
{
value = 99;
}
static void ChangeValueRef(ref int value)
{
value = 3;
}
static void Main(string[] args)
{
int a = 1;
ChangeValueRef(ref a);
ChangeValueOut(out a);
int b;
//ChangeValueRef(ref b);//报错
ChangeValueOut(out b);//不报错
}
2.out传入的变量必须在内部赋值,ref不用
static void ChangeValueOut(out int value)//报错
{
//out传入的变量必须在内部赋值 ref不用
//value = 99;
}
static void ChangeValueRef(ref int value)//不报错
{
//value = 3;
}
3.总结
1.ref和out作用:
解决值类型和引用类型,在函数内部改值或者重新申明能够影响外部传入的变量,让其也被修改。
2.使用上:
就是在申明参数的时候,前面加上ref和out的关键字,即可。使用时同上。
3.区别:
ref传入的变量必须初始化,但是在内部可改可不改(可以不赋值)
out传入的变量不用初始化,但是在内部必须修改该值(必须赋值)
1.练习1
请简要描述ref和out的区别
答案:
ref传入的变量必须初始化,但是在内部可改可不改(可以不赋值)
out传入的变量不用初始化,但是在内部必须修改该值(必须赋值)
2.练习2
让用户输入用户名和密码,返回给用户一个bool类型的登陆结果,并且还要单独的返回给用户一个登陆信息。
如果用户名错误,除了返回登陆结果之外,登陆信息为“用户名错误”
如果密码错误,除了返回登陆结果之外,登陆信息为"密码错误”
static bool CheckLogin(string name,string password,out string info)
{
//判断用户名是否正确
if (name=="admin")
{
//判断密码是否正确
if (password == "123456")
{
info = "登陆成功!";
}
else
{
info = "密码错误!";
return false;
}
}
else
{
info = "用户名错误!";
return false;
}
return true;
}
static void Main(string[] args)
{
Console.WriteLine("请输入用户名");
string name = Console.ReadLine();
Console.WriteLine("请输入密码");
string password = Console.ReadLine();
string info;
while(!CheckLogin(name, password, out info))
{
Console.WriteLine(info);
Console.WriteLine("请输入用户名");
name = Console.ReadLine();
Console.WriteLine("请输入密码");
password = Console.ReadLine();
}
Console.WriteLine(info);
}