跟siki老师学C#第八天

上一次我们学到方法的到时候说到一个参数可以是数组的情况

static void GetArray(int[] array)
{

}

这里是数组作为一个方法的参数,所以叫做数组参数,还有一个东西叫做参数数组:
在数组参数中,我们在用这个方法的时候需要把我们自己构造的这个数组传过去作为参数,而参数数组则不,它是在调用的时候把一组数据放在后面的括号里,传递过去之后,会自动地把这一组数据构造成数组并使用:

static void Array(int[] array)   //普通数组参数的方法
{

}
static void Array1(params int[] array)   //运用参数数组的方法
{

}

那么在使用的时候两种形式有什么不同呢?

Array(new int[5] { 0, 1, 2, 3, 4 });    //普通数组参数方法的使用,需要自己构造数组;
Array1(0, 1, 2, 3, 4);     //参数数组方法的使用,不需要自己构造方法,只要填入相应类型的值就可以自动构造出数组

我们在之前介绍复杂类型的时候说了枚举类型、数组和结构体,我们说的结构体就是只提到了在结构体中定义不同属性,那么既然结构体可以定义属性,那么它也可以定义方法,在结构体中定义的方法叫做结构方法,也叫做结构函数。

还是一样,我们为什么要使用结构函数呢?
我们为什么要使用结构体?因为使用结构体的话我们可以在结构体中定义若干个变量,声明一个结构体的时候,这若干个变量也都声明好了,不用我们一个一个声明了。那么这些变量需要操作,每一次操作我都要写一遍算法,那我为什么不把算法语句写在结构体中,直接调用结构体中的这个方法呢?
其实这就相当于另外写一个方法,对结构体中的变量进行操作,然后返回结果,只不过现在我们这个方法写在了结构体中而已。
我们来试试:(求直角三角形的斜边长)

struct GetBevel     //计算斜边的结构体
{
    public double x;
    public double y;

    public double GetBevels()
    {
        return Math.Sqrt(x*x+y*y);     //开平方的方法,返回值为double类型
    }
}

static void Main(string[] args)
{
    GetBevel getBevel;     //先实例化这个结构体
    getBevel.x = 3;     //给结构体的变量赋值
    getBevel.y = 4;
    Console.WriteLine("斜边长为:"+getBevel.GetBevels());    //调用结构体中的方法并获取返回值
    Console.ReadKey();
}

上面就是结构方法的用法,其实我们结构体用的相当少,结构体定义在某个命名空间下,只能这个命名空间里面的程序能用,我们一般用公共类来代替结构体,而结构方法我们也写在相应的类中,所以直接调用就好了。

接下来我们要学习的就是函数的重载。
什么叫方法或函数的重载呢?
我们知道在定义变量的时候变量名不能相同,否则编译器无法从多个同名变量中分辨出你要用的是哪个,但是方法可以,方法可以有相同的方法名,那么编译器如何去区分方法呢?
那就是方法参数,比如一个方法传递的参数是int类型的,而另一个同名函数传递的参数是double类型的,那么编译器就会根据调用时传递的参数类型去分辨到底调用的是哪个方法。
比如:

可以看到,我在上面写了两个GetBevel()方法,下面在调用的时候就显示“(共2个)”,这表示该方法共有两个重载。

static void Main(string[] args)
{
    GetBevel(3, 4);
    GetBevel(3.0, 4.0);
    Console.ReadKey();
}

我们看看运行结果:
跟siki老师学C#第八天_第1张图片
分别调用了两个方法,这就是重载,同一个方法名带上不同的参数,就会调用不同的方法,这就是重载。

接下来说的这个东西有些扯淡,至少我看完两遍没懂它是什么意思,有什么作用。
那就是委托。
委托其实说的是一种类型,与int、string、char都一样,但是又很特殊,因为其他类型一般都是指向变量,但是委托却是指向方法。
比如:

int value=3;

int类型也就这样用了,暂时还玩不出什么新花样,但是委托,呵呵!

MyDelegate delegates;   //MyDelegate是自己定义的委托类型 delegates是委托变量
delegates = Add;    //Add是一个方法

你敢信?变量可以等于方法,可以等于方法。。我们之前顶多遇到过变量等于方法。。。的返回值,但是这里直接等于方法啊!!

别的类型的变量不可以,委托的就没问题。。真是醉了。
委托类型的变量等于一个方法后,这个变量就成了一个方法,我们可以用这个变量去直接调用这个方法,因为这个变量已经指向这个方法了,这就是委托的作用:把一个委托类型的变量指向一个方法。

说了委托的作用,那么委托类型是怎么定义的呢?
看个实例吧:

namespace CSharp学习第七课
{
    class Program
    {
        //delegate为关键字 定义好了一个委托类型OneDelegate
        delegate int OneDelegate(int num1,int num2);

        static int Add(int num1, int num2)
        {
            return num1 + num2;
        }

        static void Main(string[] args)
        {
            OneDelegate oneDelegate;    //用定义好的OneDelegate去声明一个该类型的变量oneDelegate
            oneDelegate = Add;   //变量等于方法
            int res = oneDelegate(3,4);    //变量直接调用它所指向的方法
            Console.WriteLine(res);
            Console.ReadKey();
        }
    }
}

最终结果:
跟siki老师学C#第八天_第2张图片

我还是云里雾里的,反正先知道有委托这个东西就好了,以后能用到的话我们再通过实际应用来加深理解!

接下来我们说的就很常见了,而且上次我们遇到一个问题没有解决,现在也可以解决了,那就是函数的递归调用。
递归是相对于函数来说的,脱离了函数,递归也就无从谈起,因为函数实在返回值返回的地方做手脚的。

一般带有返回值的函数,我们最终返回的是结果,但是用了递归的话,返回值就不是最终结果的值了,而是返回该函数参与的运算,因为该运算写在方法里,所以出现了在方法里调用该方法的情况。这就叫函数的递归调用。
比如一个函数计算的是一个等于前两个数字之和:

static int Function(int num) {
    return Function(num - 1) + Function(num - 2);
}

返回值里面又出现了该方法。
既然返回值调用了自身,那么这个递归循环什么时候才能终止呢?如果不给它条件的话,这就一个死循环,所以要给它终止条件。

static int Function(int num) {
    if(num==0)
    {
        return 2;
    }
    if(num==1)
    {
        return 3;
    }
    return Function(num - 1) + Function(num - 2);
}

在主函数中我调用这个方法:

Function(40);

这个语句会将Function(40)的结果分解为许多Function(0)+Function(1)的形式相加,最终将2和3代入最终算式算出结果。

以现在CPU的运算速度,这个Function(40),还要花费一定的时间才能得到结果,因此递归的调用在运算时还是比较占用CPU的。

既然现在我们学习了递归调用了,那么我们来做一做之前的练习题吧:

兔子繁殖问题。设有一对新生的兔子,从第三个月开始他们每个月都生一对兔子,新生的兔子从第三个月开始又每个月生一对兔子。按此规律,并假定兔子没有死亡,20个月后共有多少对兔子?要求编写为控制台程序。

既然我们知道这里需要用递归来实现,那么我们就要想想算法,实际上算法不是很容易想的,像这里,至少我这麻瓜脑袋想了一天没想出来。
既然是用到递归,那么不可避免的是要用到公式的。所以我们想不出算法就去推导递归的公式。
第一个月:f(1)=1;
第二个月:f(2)=1;
第三个月:f(3)=2;
第四个月:f(4)=3;
第五个月:f(5)=5;
第六个月:f(6)=8;
可以推导出f(n)=f(n-1)+f(n-2)。
同样的,我们的递归必须有一个终止条件,既然是月份,那么计算肯定是从第一个月和第二个月开始,而公式的分解最终也就是需要f(1)和f(2)。
这样一来就很简单了:

namespace CSharp学习第八课
{
    class Program
    {
        static int GetRabbit(int month)
        {

            if(month==1||month==2)
            {
                return 1;
            }
            return GetRabbit(month-1)+GetRabbit(month-2);
        }

        static void Main(string[] args)
        {
            Console.WriteLine(GetRabbit(20));
            Console.ReadKey();
        }
    }
}

因此我们可以总结:递归算法中公式是相当重要的!

总结:
1.参数数组的概念,用法以及与数组参数的区别;
2.什么叫结构函数以及结构函数的用法;
3.什么是函数的重载;
4.什么叫委托;
5.递归的用法以及递归最重要的关键点(公式);
6.用递归解决一般问题的思路;

以上就是学习的内容,C#第一阶段就学到这里,接下来要进行下一阶段的学习。对于博客中存在的错误,欢迎大家批评指正!感激不尽!!

你可能感兴趣的:(C#)