一:知识点流程
二:定义方法,调用方法,递归调用
1.定义方法:
①:方法是把一些相关的语句组织在一起,用来执行一个任务的语句块。
②:语法
③例:
public static void exchange(int a,int b)
{
int exchange;
exchange = a;
a = b;
b = exchange;
}
备注:访问权限是允许访问该类或该成员变量或该函数的范围,类的默认访问标识符是 internal,成员的默认访问标识符是 private。
2:调用方法
①:静态调用
②:非静态调用
class Program
{
public static int Add(int a,int b)
{
return a + b;
}
public int Sub(int a,int b)
{
return a - b;
}
}
class test
{
static void Main(string[] args)
{
//静态调用:不需要实例化对象
int sum =Program.Add(10, 20);
Console.WriteLine($"10+20={sum}");
//非静态调用
Program pro = new Program();
int sub= pro.Sub(20,10);
Console.WriteLine($"20-10={sub}");
Console.ReadLine();
}
}
运行结果:
③:递归调用(函数调函数,注意不要造成死循环)
public static int factorial(int num)
{
/* 局部变量定义 */
int result;
if (num == 1||num==0)
{
return num;
}
else
{
result = factorial(num - 1) * num;
return result;
}
}
static void Main(string[] args)
{
Console.WriteLine($"0的阶乘:{factorial(0)}");
Console.WriteLine($"1的阶乘:{factorial(1)}");
Console.WriteLine($"10的阶乘:{factorial(10)}");
Console.ReadLine();
}
运行结果:
三:参数传递
1:按值传递(重点:传递的是值!)
①:例
static void Main(string[] args)
{
int a = 100, b = 200;
//按值传递参数
exchange( a, b);
Console.WriteLine("-----我是分割线---------");
Console.WriteLine("a={0};b={1}",a,b);
Console.ReadLine();
}
public static void exchange(int a, int b)
{
int exchange;
exchange = a;
a = b;
b = exchange;
Console.WriteLine("exchange={0}",exchange);
Console.WriteLine("a={0}", a);
Console.WriteLine("b={0}", b);
}
运行结果:
③:底层分析:
//mov:数据传送指令
目的操作数:ecx,edx 源操作数:dword ptr [ebp-40h],dword ptr [ebp-44h]
02DB4103 mov ecx,dword ptr [ebp-40h]
//翻译:
ecx=dword ptr [ebp-40h]=100;//exchange(a, b); a=100
02DB4106 mov edx,dword ptr [ebp-44h]
//翻译:
edx=dword ptr [ebp-44h]//exchange(a, b); b=200
备注:mov指令只是做到了值的传递,拷贝复制过程,没有涉及到地址,所以这里的a=200 b=100也只是局限于"exchange(int a, int b)"这个函数(方法)内部,只在这个作用域下起作用。
2:按引用传递参数 ref(重点传递的是地址!)
①:例
static void Main(string[] args)
{
int a = 100, b = 200;
//按引用传递参数
exchange(ref a,ref b);
Console.WriteLine("a={0};b={1}",a,b);
Console.ReadLine();
}
public static void exchange(ref int a, ref int b)
{
int exchange;
exchange = a;
a = b;
b = exchange;
}
②:运行结果:
③:底层原理
这里采用的是lea指令,对于变量而言传递的是地址。(和mov指令相反)
016345A1 lea ecx,[ebp-40h] //ecx=ebp-40h
016345A4 lea edx,[ebp-44h] //edx=ebp-44h
④:注意
注意1:
注意2:传参必须赋值!
备注:引用参数是一个对变量的内存位置的引用(lea指令)。当按引用传递参数时,与值参数不同的是,它不会为这些参数创建一个新的存储位置。引用参数表示与提供给方法的实际参数具有相同的内存位置。
3:输出类型 out
①:可以把输出参数看成数据返回参数
②:和ref相似处:
ref和out都是传递地址,底层操作基本一致。
必须以out一起传递。(调用时都需要输入相应的关键字)
③:和ref不同处
可以使用未赋值的局部变量
不能使用未赋值的out参数
④:例:
using System;
namespace CalculatorApplication
{
class NumberManipulator
{
public void getValues(out int x, out int y )
{
Console.WriteLine("请输入第一个值: ");
x = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("请输入第二个值: ");
y = Convert.ToInt32(Console.ReadLine());
}
static void Main(string[] args)
{
NumberManipulator n = new NumberManipulator();
/* 局部变量定义 */
int a , b;
/* 调用函数来获取值 */
n.getValues(out a, out b);
Console.WriteLine("在方法调用之后,a 的值: {0}", a);
Console.WriteLine("在方法调用之后,b 的值: {0}", b);
Console.ReadLine();
}
}
}
运行结果:
备注:当需要从一个参数没有指定初始值的方法中返回值时,输出参数特别有用。
相关链接:汇编常用指令