第4章定义类——方法上一章中我们介绍了如何定义类的成员——字段,这一章我们继续来学习如何定义类的另外一个成员——方法。方法是包含一系列语句的代码块,它可以改变对象的状态。我们将在这一章中给大家介绍如何定义方法以及方法中用到的一些其他知识如参数、返回值、语句等。4.1方法的概述方法是在类中定义的,其中包括了一组在同一名字下的语句。在C#中,每个执行指令都是在方法的上下文中完成的。4.1.1定义方法要利用方法,我们首先应该学习一下如何定义方法。方法在类中声明,最基本的声明格式如下图所示。(参数)返回值类型方法名参数列表,空括号表示不需要参数//方法主体语句访问修饰符任何数据类型,如果无返回值,则需写void有意义的标识符,符合标识符命名规范{}定义方法【示例4-1】演示的是声明带参数的和不带参数的方法的方式。publicvoidStartEngine(){}privatefloatAddGas(intgallons){}公用的方法,无返回值,且没有参数私有的方法,返回值为浮点型,有一个整型的参数4.1.2方法的调用方法的执行,也就表明方法被调用。我们来看一下,类的方法和对象的方法分别是如何调用的。1.类的方法及其调用类的方法主要是指静态方法。使用了static修饰符的方法为静态方法,其声明格式如下图所示。【示例4-2】演示的是静态方法的声明及使用方法。static返回类型方法名(){//方法主体}方法的调用2.对象的方法及其调用对象的方法主要是指非静态方法。未使用static修饰符的方法称之为非静态方法,其声明格式与普通方法一致,在此不再表示。非静态方法既可以访问类中的静态成员,也可以访问非静态成员。非静态方法属于对象,需要通过实例化的对象来进行访问。【示例4-3】演示的是非静态方法的声明及使用方法。4.2方法体的构成知道了方法如何定义以及如何调用后,我们有必要来了解一下方法体都由那些部分构成,这就是我们这节的重点。4.2.1局部变量方法可以改变对象的状态,改变有时候需要一些中间值,C#语言提供了局部变量。在方法中声明的变量称为局部变量,它是相对于全局变量而言的,全局变量我们在下一小节会讲到。“局部”的意思主要是在这个方法中声明的局部变量不能被其他方法使用。局部变量【示例4-4】演示的是局部变量的声明方法。staticvoidMain(string[]args){boolmyBool=true;{intmyint=5;myBool=false;}……}myBool是个局部变量,只能在main()方法中用myint也是个局部变量4.2.2局部变量与字段同名的解决——THIS关键字在类的方法中,方法的局部变量可能会与类的字段同名。这时候,不能直接使用同名的标识符访问该字段。为解决该问题,C#引入了this访问方式,语法如下图所示。【示例4-5】演示的是使用this关键字访问字段。在类的方法中出现的this作为一个值类型,它表示对调用该方法的对象的引用;而静态字段从根本上来说是属于类的,因此不能用this去访问静态字段。【示例4-6】演示的是this不能访问静态字段。this.字段名this相当于类的对象4.2.3语句方法的主体中包括了一系列的语句,它可以帮助实现方法的功能,因此我们在这里介绍一下语句的知识。C#中包括声明语句、表达式语句、选择语句、迭代语句、跳转语句等多种语句。语句的声明我们在前面已经有过接触,如声明字段。这儿只介绍最简单的表达式语句,其他语句将在第五章中详细给大家介绍。1.语句声明在C#中,语句是可以改变程序当前状态的单一实体,表达式语句的声明形式如下图所示。这里需要提醒大家一下:如果忘记分号将会导致编译器错误,同时语句可以改写成多行,排列有序而且很容易理解。;;表达式表达式语句2.块和作用域在一个方法中语句会比较多,因此出现了“块”,将语句放到块里可以清晰划分工作单元的起点和终点,代码块的开始位置是左大括号({),并以右大括号(})结尾。块还确立了作用域,,局部变量的作用域就是从变量声明开始,到局部变量所在的块的右大括号结束。【示例4-7】演示的是块和作用域的范围。staticvoidMain(string[]args){boolmyBool=true;{intmyint=5;myBool=false;}myint=6;}语句块1的作用域语句块2的作用域错误!超出了myint的作用域myBool的作用域myint的作用域4.2.4全局变量全局变量也称为外部变量,它是在函数外部定义的变量。它不属于哪一个函数,它属于一个源程序文件,其作用域是整个源程序。全局变量的说明符为extern。【示例4-8】演示的是全局变量的声明方式。externinta,b;classProgram{voidf1(){ //函数主体 } voidmain(){ //函数主体}}定义的全局变量全局变量a和b的作用域4.3返回值在C#中,方法与函数是一样的。返回值是通过方法(或函数)进行数据交换的最简单方式。有返回值的方法(或函数)会计算这个值,其方式与在表达式中使用变量计算它们包含的值完全相同。4.3.1返回值类型与变量一样,返回值也有数据类型。返回类型指明了当方法完成时什么类型的值被返回,它可以是任何一种数据类型。返回类型通常标在方法名前。【示例4-9】演示的是返回值类型为整型的方法。需要注意的是,返回的值必须与返回值类型兼容,即要么是同一类型要么可以相互转化,否则会提示出错。staticintMain(){return0;}返回值为整型返回值类型【示例4-10】演示的是返回值类型与方法体类型不兼容的情况。方法并不是必须返回值,如果方法没有返回任何值,则必须在返回值的位置写上“void”。【示例4-11】演示的是返回值为空的Main()方法。staticvoidMain(){}返回值为void类型返回值为void类型4.3.2从方法返回方法的作用是改变对象的状态,因此要使方法返回。通常,有两个条件可以使方法返回。第一,在遇到方法的右大括号时,会从方法返回。【示例4-12】以下代码演示的是方法的执行遇到方法的右大括号,从方法返回。publicvoidAreaPerPerson(){Console.WriteLine(“”+Area/Occupants+“areaperperson”);}遇到方法的右大括号,方法返回从方法返回第二,执行return语句。在void类型的方法中,使用return语句的“return;”形式将立即终止该方法。【示例4-13】演示的是方法的执行遇到return语句,就返回。小结一下,void类型的方法的返回有两种方式:遇到方法的右大括号或者执行一条return语句。但是提醒大家注意:一个方法中有多个退出点可能会破坏代码的结构,因此应该尽量避免随意使用return语句。4.4参数在调用方法时,可以给方法传递一个或多个值,称为参数。每个方法中可以有一个参数,也可以有多个参数。每个参数都有一个类型和一个名称,多个参数时需要用逗号分隔开来,参数声明的格式如下图所示。(参数类型参数名1,参数类型参数名2,……)参数【示例4-14】演示的是参数的声明。staticdoubleProduct(doubleparam1,doubleparam2){returnparam1*param2;}两个double型的参数4.4.1参数的分类函数的参数分为形参和实参两种,在这一小节中我们将分别给大家介绍这两种参数以及这两者的关系。1.形式参数在定义函数名和函数体的时候使用的参数,目的是用来接收调用该函数时传递的参数。【示例4-15】演示形式参数的声明方式。publicboolIsPrime(intx){if(x=1)returnfalse;}这里的参数x就是形式参数,参数类型为整型参数的分类2.实际参数实参是在调用时传递给函数的参数。实参可以是变量、表达式或函数,无论实参是何种类型的量,在进行函数调用时,它们都必须具有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使实参获得确定值。【示例4-16】演示实际参数的声明方式。voidmain(){inti=5,p;p=Max(i);}这里的参数i就是实际参数,把5传递给函数Max()参数的分类3.形参与实参的关系1、形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量。2、实参和形参在数量上,类型上、顺序上应严格一致,否则就会发生类型不匹配的错误。【示例4-17】以下代码演示形参和实参类型匹配的关系。staticvoidMyFunction(charmyChar,doublemyDouble){}MyFunction('X');MyFunction(2.66,'X');参数类型不匹配,不能调用参数个数不匹配,不能调用4.4.2引用参数(REF参数)值传递有时候只能改变要处理的变量,而做不到改变用作参数的变量。因此我们引入一种新的参数——引用参数,它属于形参中的一种。用ref修饰符声明的参数称为引用参数,使用引用参数可以改变用作参数的多个变量值。形式参数的声明格式如下图所示。【示例4-18】演示引用参数为值类型的情况。【示例4-19】演示引用参数为引用类型的情况。(ref参数类型参数名)4.4.3输出参数(OUT参数)函数的返回值一般来说只有一个,但是有时候我们需要返回的值超过了一个,C#为此有了一种新的参数类型——输出参数,输出参数的声明格式如下图所示。在函数的实参中,输出类型的那个参数前必须加上out关键字,否则程序会报错。而且应该注意到得是在函数使用out参数时,它必须看作是还未赋值的,即使我们传递了值给它。在return语句返回值之前,必须给输出参数赋值,否则也是会报错的。【示例4-20】以下代码演示输出参数类型的用法。(out参数类型参数名)4.5特殊的方法在C#语言中,有几种方法是特殊但又比较常用的,我们在这一节给大家介绍一下,主要包括Main()方法、构造函数和析构函数。4.5.1MAIN()方法Main()是C#应用程序的入口点。在执行过程开始时,会执行Main()函数,在Main()函数执行完毕时,执行过程就结束了。Main()函数的返回值最终是给系统用,因此可以返回void或int类型,并且有一个可选参数string[]args。Main()函数可以使用如下四个版本:staticvoidMain()staticvoidMain(string[]args)staticintMain()staticintMain(string[]args)上面的第三、四个版本返回一个int值,它们可以用于表示应用程序如何终止,通常用作一种错误提示(但这不是强制的),一般情况下,返回0反映了“正常”的终止(即应用程序执行完毕,并安全地终止)。4.5.2构造函数构造函数用于在创建对象时初始化对象。它与类有相同的名称,而且在语法上类似于方法,但是,构造函数没有显式的返回值类型。构造函数的声明格式如下图所示。构造函数会在实例化对象时自动调用已经初始化的实例变量,同时C#自动提供了默认的构造函数,他将所有的成员变量设置为0(值类型)、false(布尔类型)或null(引用类型)。但是一旦定义了自己的构造函数,就不再使用默认的构造函数。【示例4-21】以下代码演示自定义构造函数的用法。public类名(参数列表){//函数主体}默认设置为public可以为空,或者指定一个或多个参数4.5.3带参数的构造函数带参数的构造函数在实例化对象时提供实参,然后将其传递给形参,继而传递给成员字段,对象调用字段输出结果。带参数的构造函数的声明格式如下图所示。【示例4-22】以下代码演示带参数的构造函数的用法。public类名(参数列表)4.5.