C#方法(完整篇-包含了:参数(out,ref)的关键字,方法调用顺序,方法的栈帧以及递归调用实现斐波那契数列等内容)

目录

一.基本定义:

        1.方法的基本组成:

        2.方法的基本分类;

二.方法的使用(设计与调用)

三.var(variable变量)与命名参数

var:

命名参数:

四.方法中变量作用域

五.参数的关键字

1.params参数(可变参数)

2.out参数(输出参数)

3.ref(引用传递)

六.值传递和引用传递

七.方法的调用顺序

1.调用多个方法,方法直接没有联系时

2.调用多个方法,方法有联系时(嵌套)

八.方法的栈帧

九.方法的递归调用

十.斐波那契数列(Fibonacci sequence)


一.基本定义:

        类中函数,称方法,又称行为;

        1.方法的基本组成:

(1)方法修饰符:public   和 static;

(2)返回值:void没有返回值,有返回值的需要配合return;

(3)方法名称:命名规则:大驼峰;

(4)形参列表:形参就是形式参数,将来用实参来传递形参;()中就是方法形参,  形参不固定。

(5)方法体 :在{}中;

[public] [static] 返回值类型 方法名字([参数列表])
{
	方法体
}

        2.方法的基本分类;

          静态方法、实例方法、无参方法、有参方法

          静态方法:使用static,只存于类本身,只能通过类本身访问,不能通过实例访问即个体实              现;如:

public static void Add(int a,int b){}

          实例方法:没有使用static 修饰符修饰的方法,,必须通过类的个体实现;

          无参方法:就是()中没有值;

public  void Add(){}

         有参方法:就是()中有值;

public  void Add(int a,int b){}

二.方法的使用(设计与调用)

        1.方法:当返回值为void,不需要返回值即return;

public  void Add(int a,int b)
        {
            result = a + b;
            Console.WriteLine(result);
        }

           输出:此时只需传参就可以调用方法

var clac=new Clac();//实例化
clac.Add(10,20);//调用方法,Add(10,20)是传参
//在本类中调用,不需实例化,直接调用方法即可

      2.当返回值为基本数据类型时,需要return;

public float Add(float a,float b) { 
        return a + b;
        }

           输出:因为此时有返回值,所以需要输出打印

var res = clac.Add(12.5f,25.3f);
Console.WriteLine(res);
//也可以简写
Console.WriteLine(clac.Add(12.5f, 25.3f));

      3.一个方法返回值的类型可以和形参的类型不一样;

public string Add(float a, float b,float c)
        { 
        return (a+b+c).ToString();//TOstring 转字符串类型
        }

三.var(variable变量)与命名参数

var:

在C#中,原来定义变量需要基本数据类型,现在C#中提供一个关键字var(variable变量),专门用来定义变量,它定义的变量不需要指定的类型,变量会根据变量值进行【类型推断】,如:

var a = 10;

命名参数:

方法的实参和形参类型要保持高度一致,传递顺序也要高度一致;如果开发者传递实参实时,没有和形参保持一致,又想让代码执行成功,怎么办?

答:给实参起别名;命名参数可以让开发者给实参指定传递位置

 public static int Add(int a,int b) 
        {
            Console.WriteLine($"a的值:{a},b的值{b},结果{a+b}");
            return a + b;
        }
//输出
Clc.Add(20,10);
Clc.Add(b:20,a:10);
//输出结果:a的值:20,b的值10,结果30
//          a的值:10,b的值20,结果30

四.方法中变量作用域

作用域是在指当前方法内,比如想让一个变量在多个方法中使用,那么就需要把这个变量的作用域扩大,如何扩大?  可以将其定义到类中(注意:此时的变量与方法中的变量虽然一样,但是却不是同一个)。如:

public   class Calc
    {
         int result;//扩展到类范围
        public int Add(int a, int b)
        
            result = a + b;//此变量和外部变量return不是同一个
            return result;
        }
        public  void Fun1()
        {
            //result变量必须在当前上下文中定义才能使用
            Console.WriteLine(result);//想要使用result 就要扩展扩展,此处调用的是外部return
        }
        
    }
//调用
var clc = new Calc();
clc.Fun1();                   //结果: 0  此时return还没有返回外部return
var res= clc.Add(10, 20);
Console.WriteLine(res);       //结果: 30
clc.Fun1();                   //结果: 30

五.参数的关键字

1.params参数(可变参数)

可变参数语法要求:
        1.使用patams关键字来标识此参数是可变参数
        2.可变参数必须是方法的最后一个形参;
        3.可变参数不是说类型可变,而是指个数可变

public void Add2(params int[] arr) 
{
   Console.WriteLine($"索引{arr[0]},索引{arr[1]},索引{arr[2]},索引{arr[3]}");
        }
//输出:
MyClass myClass = new MyClass();   //实例
var arr = new int[] { 0,1, 2, 3 }; //给形参数组传参
myClass.Add2(arr);

2.out参数(引用传递)

  1. 可以帮助我们在一个方法中返回多个值,不限类型。
  2. 使用out参数的时候,要求out参数必须在方法内为其赋值,也就是在方法内进行初始化,即使赋值了也会被清空,out也是引用传递,
  3. out用法:一般用于需要返回多个参数时,如在需要返回分页的数据时 同时返回总条数或者TryParse()会用到
   public void Add3(int a,out int b) 
        {
            b = a + 10;
            //之前b想要在调用Add3的时候得到b,需要借助return;
            //现在也可以借助out转出参数,实现和return相同的效果
        }
//输出:
int res3 = 0;           //先定义初始值,
myClass.Add3(1,out res3);//进入方法体,得到b为11,在输出初来给res3
Console.WriteLine(res3);

3.ref参数(引用传递)

 ref用法:一般用于在改变一个参数时,把他的改变反应到变量中 如在递归中

在方法中修改ref参数会影响外部变量

 public void Add4(int a,ref int b)
        {
            a = 20;
            b = 10;
            Console.WriteLine($"内部a的值{a},內部b的值{b}");
        }
//输出:
a = 200;    //先传到形参
int b = 100;//先传到形参
myClass.Add4(a,ref b);
Console.WriteLine($"外部a的值{a},外部b的值{b}");
//结果:
//内部a的值20,內部b的值10
//外部a的值200,外部b的值10

总结:ref和out值必须是可以赋值的变量,也就是说需要进行初始化

六.值传递和引用传递

值传递:方法中修改了形参,不影响外部的实参;

引用传递:方法中修改了形参,影响外部的实参;

值传递有哪些?

答:1.基本数据类型都属于值传递

        2.string类型的值传递:

       直接使用string类型传递,也没有借用类调用 ,相当于重新定义参数,会生成新的内存空间,所以实参地址不会改变;也即字符串会产生新的地址;

假设实参为name,x形参name2;那么开始时实参传给形参即:name2=name(地址一样),

但在方法中又对name2="小白"即产生新的地址,故而name2的地址也随改变

引用传递有哪些?

答:1.数据类型前面加  关键字ref ;据类型前有ref表示传递的数据是引用类型,是地址;

        2.string类型的引用传递:

          借用类的实例,修改属性时没有生成新的内训地址

          在类加载期间,将字符串添加到字符串常量池中,再添加字符串会判断字符串内容是否存在池中,若存在便不会分配内存空间,故而会导致地址的改变。       

string str=null;为空是不会分配内存空间的;

string str=" ";表示占用了一个位置,因此会分配地址

七.方法的调用顺序

1.调用多个方法,方法直接没有联系时

1.代码执行顺序,默认从上到下()按调用顺序,先执行Fun1,在执行Fun2;

2.当代码遇见开发者封装方法时,会进入方法体执行,之星结束,返回到调用方法处;如果代码遇见的不是开发者封装的方法,而是C#内置的类库提供的方法,这时候并不会进入到方法体。
原因:类库提供的方法源码是隐藏的;

var class1 = new Class1();
class1.Fun1(); //Class1中的Fun1()中,方法体执行完后,会返回到此行代码;
class1.Fun2();//Fun1.Fun2是方法名

2.调用多个方法,方法有联系时(嵌套)

//方法嵌套调用  这几个方法之间存在联系
        public void Fun3()
        {
            Console.WriteLine("我是fun3");
            Console.WriteLine("我是fun3.1");
            Fun4();
        }
        public void Fun4()
        {
            Console.WriteLine("我是fun4");
            Console.WriteLine("我是fun4.1");
            Fun5();
        }
        public void Fun5()
        {
            Console.WriteLine("我是fun5");
            Console.WriteLine("我是fun5.1");
        }
//调用:
class1.Fun3();
//结果:我是fun3
//我是fun3.1
//我是fun4
//我是fun4.1
//我是fun5
//我是fun5.1

注意:重点来了

看完输出结果,此时会不会觉得调用顺序是先把Fun3执行完,再执行Fun4,再执行Fun5错误顺序),其实不然。                                                                                                       

  可以通过断点判断出真正的顺序:F3(没执行完)-F4(没执行完)-F5(一次性执行完)-F4(完)-F3(完)                                                                                                       

进入的顺序:方法嵌套的顺序F3-F4-F5;                                                                                执行的顺序:F3-F4-F5                                                                                                              执行完毕顺序:F5-F4-F);先进后出

八.方法的栈帧

方法调用的栈帧:就是执行方法时,给方法分配的内存空间;
方法执行时,只要分配了内存空间,调用方法,会进入此内存空间。内存空间执行顺序就叫做“调用栈”;
调用栈其实就就是先进后出,这个栈帧的执行顺序我称之为:是一个U型结构;

九.方法的递归调用

在一个方法中,调用方法本身,简言之就是:自己调用自己
递归拥有一个自循环。递归要小心地是:一定要有出口(方法可以停止)。                            递归没有出口,就会进入“死循环”,出现栈溢出的错误;

代码演示:

private int count = 3;
        public void Count() {
        Console.WriteLine($"当前是:{count}");
            if (count-- == 0)
            {
                return;
            }
            Count();//调用自己
        }
//调用:
class1.Count();
/*输出结果:当前是:3
            当前是:2
            当前是:1
            当前是:0   */

十.斐波那契数列(Fibonacci sequence)

斐波那契数列(Fibonacci sequence),又称黄金分割数列,因数学家莱昂纳多·斐波那契(Leonardo Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:1、1、2、3、5、8、13、21、34、……在数学上,斐波那契数列以如下被以递推的方法定义:F(0)=0,F(1)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 2,n ∈ N*)
代码演示:

public int Fib(int n) 
        {
            if (n == 0)
            {
                return 0;
            }
            else if (n == 1)
            {
                return 1;
            }
            else
            { 
            return Fib(n - 1)+Fib(n-2);
            }
        }
//输出:
Console.WriteLine(class1.Fib(0));
Console.WriteLine(class1.Fib(1));
Console.WriteLine(class1.Fib(2));
Console.WriteLine(class1.Fib(3));
Console.WriteLine(class1.Fib(4));
Console.WriteLine(class1.Fib(5));
//结果:0 1 1 2 3 5

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

薄荷撞~可乐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值