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),如果形参不带ref
或out
修饰符,那么它的值的变化不会影响实参,它相当于实参的一份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
是一个整数类型的形参,ave
和sum
都带着ref
,这个两个都是引用参数。
先说说引用参数,引用参数使用的时候要在类型前加上ref
,方法的声明和调用都要带上ref
。引用参数的作用是实参的值会传入形参中,形参在方法体内进行一系列的操作之后,它的值会返回给实参,就是说形参的改变会引起实参的改变。拿上面的程序来说,ave
和sum
打印出来的结果是5.5和55。值得注意的是第42行中,sum
和array.Lenghth
经过了强制类型转换从int
转换为double
再进行除法运算。尽管在Main
函数中,max
和sum
的值被初始化为0,但是引用参数会改变实参的值。
与之相似的就是输出参数了,带上out
的就是输出参数。既然是类似,我们就对比着来说,在方法的声明和调用时,输出参数都要带上out
。与引用参数不同的是,输出参数只会输出:在方法内进行一系列操作后,输出参数的值会返回给对应的实参;实参是否初始化不影响输出参数的使用,因为输出参数规定要在方法体内初始化,比如第27、29行,所以你实参是否进行初始化并不影响使用,也不会报错。看上面的程序,max
就是输出参数,最后打印的结果为10。
下面最关键的来了,min
会打印出什么呢?1吗?肯定不是。实参min
的默认值为0,方法体中的形参被初始化为array[0]
,在方法体内最后形参min
的值肯定是1,但是,这个值会返回给实参min
吗?不会的,因为它既不是引用参数,也不是输出参数,所以形参的值无法传给实参,最终打印出min
的结果为0。
有一点C基础的人肯定知道怎么去把形参的值返回给实参——指针,但是C#不推荐你使用指针,把指针设为了“不安全代码”,所以大家要把形参实参挂钩的话,多用输出参数和引用参数吧。
方法的调试百度吧,逐语句跟踪变量,yyds
后续coming soon...(perhaps)