C#方法

C#方法

继续填坑复习,上次讲完类型和变量,这次讲讲方法。
方法(method)的前身是C/C++语言的函数(function)。方法是面向对象范畴的概念,在非面向对象语言中仍然称之为函数。方法永远都是类或结构体的成员,C#语言中函数不可能独立于类或结构体之外,只有作为类或者结构体的成员时才能被称为方法。方法是类或结构体最基本的成员之一(最基本的成员只有两个——字段和方法,本质上是数据+算法)。

方法的声明与调用

C#中的方法要在类或者结构体里面声明,所以声明的时候要留意位置对不对,不要在名称空间里面声明,会报错的。C#的方法声明和C差不多,访问修饰符+返回值类型+方法名+参数列表。下面看一段代码:

using System;

namespace SomeNotes
{
    class Program
    {
        public static void Main(string[] args)
        {
            int a = 1, b = 2;
            int result = Add(a, b);
            Console.WriteLine(result);

            Printer printer = new Printer();
            printer.SayHello();
        }

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

    class Printer
    {
        public void SayHello()
        {
            Console.WriteLine("Hello World!");
        }
    }
}

第17行我声明了一个叫Add的方法,用static是为了不实例化就使用它,如果一个方法没有带访问修饰符的话,它默认会给你一个internal的访问权限,意思就是在同一个程序集里面可见。后面的int就是返回一个整数类型的值,括号里面的就是参数列表了,两个int类型的参数。进入函数体里面,返回一个a + b的值,函数的声明就完成了。
回到Main函数里面,第10行调用了Add,把 a 和 b 的值传进Add中,然后返回值赋给result,最后打印result的值为3。
上面讲的是静态方法,用static修饰的方法就是静态方法,指的是不用实例化就能使用。下面还有一个叫SayHello的方法,它的访问修饰符是public,返回值为void(没有返回值,这类方法一般是执行一些操作),参数列表为空。进入方法体内,它只干了一件事,打印一行字。
再回到Main函数里面,第13行我用一个Printer类型的变量printer去引用一个Printer的实例,然后调用printer里面的方法,也就是SayHello,控制台就会打印一行“Hello World!”。
静态成员在类的第一次加载的时候就全部加载出来了,所以静态方法不需要实例化也能调用;后面的SayHello则不能直接调用,要先声明一个实例,然后通过实例去调用。
函数的参数叫做形式参数(parameter),传入函数的参数(不是在函数里面声明的)叫做实际参数(argument),如果形参不带refout修饰符,那么它的值的变化不会影响实参,它相当于实参的一份copy,就算它们同名,一样不会有影响。

引用参数和输出参数

先上一段代码吧,看着代码来解释。

using System;

namespace SomeNotes
{
    class Program
    {
        public static void Main(string[] args)
        {
            int max, min = 0, sum = 0;
            int[] nums = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
            double ave = 0;

            Calculator calc = new Calculator();
            calc.GetStatistics(nums, out max, min, ref ave, ref sum);

            Console.WriteLine(max);
            Console.WriteLine(min);
            Console.WriteLine(sum);
            Console.WriteLine(ave);
        }
    }

    class Calculator
    {
        public void GetStatistics(int[] array, out int max, int min, ref double ave, ref int sum)
        {
            max = array[0];
            min = array[0];
            sum = 0;
            for (int i = 0; i < array.Length; i++)
            {
                if (array[i] > max)
                {
                    max = array[i];
                }
                if (array[i] < min)
                {
                    min = array[i];
                }
                sum += array[i];
            }
            ave = (double)sum / (double)array.Length;
        }
    }
}

有点长,但是不要怕,一个个来看。GetStatistics这个方法它干了四件事,算出最大值、最小值、平均值和总和,注意看参数列表里面,array是一个整数类型的数组,max的前面除了int,还多了一个out,带着out修饰的参数就是输出参数。先继续看,min是一个整数类型的形参,avesum都带着ref,这个两个都是引用参数。
先说说引用参数,引用参数使用的时候要在类型前加上ref,方法的声明和调用都要带上ref。引用参数的作用是实参的值会传入形参中,形参在方法体内进行一系列的操作之后,它的值会返回给实参,就是说形参的改变会引起实参的改变。拿上面的程序来说,avesum打印出来的结果是5.5和55。值得注意的是第42行中,sumarray.Lenghth经过了强制类型转换从int转换为double再进行除法运算。尽管在Main函数中,maxsum的值被初始化为0,但是引用参数会改变实参的值。
与之相似的就是输出参数了,带上out的就是输出参数。既然是类似,我们就对比着来说,在方法的声明和调用时,输出参数都要带上out。与引用参数不同的是,输出参数只会输出:在方法内进行一系列操作后,输出参数的值会返回给对应的实参;实参是否初始化不影响输出参数的使用,因为输出参数规定要在方法体内初始化,比如第27、29行,所以你实参是否进行初始化并不影响使用,也不会报错。看上面的程序,max就是输出参数,最后打印的结果为10。
下面最关键的来了,min会打印出什么呢?1吗?肯定不是。实参min的默认值为0,方法体中的形参被初始化为array[0],在方法体内最后形参min的值肯定是1,但是,这个值会返回给实参min吗?不会的,因为它既不是引用参数,也不是输出参数,所以形参的值无法传给实参,最终打印出min的结果为0。
有一点C基础的人肯定知道怎么去把形参的值返回给实参——指针,但是C#不推荐你使用指针,把指针设为了“不安全代码”,所以大家要把形参实参挂钩的话,多用输出参数和引用参数吧。

方法的调试百度吧,逐语句跟踪变量,yyds

后续coming soon...(perhaps)

posted @ 2020-09-26 15:41  Jay_Auditore  阅读(430)  评论(0编辑  收藏  举报