您好,欢迎访问三七文档
第5章函数、域与属性计算机科学系——毕好昌2011年3月主要内容函数的定义、使用属性与域的定义以及使用C#中函数的定义在大多数的应用软件的设计中,将应用程序分成若干个功能单元。由于小段的程序更易于理解、设计、开发和调试,因此采用功能单元是应用程序设计的核心法则。分为若干个功能单元以便在应用程序中重用功能构件。另外,在整个大的程序中,某些任务常常要在一个程序中运行好多次,举个最简单的例子,对多个数组进行排序。此时我们就可以把这些相同的代码段写成一个单独的单元,需要的时候我们就来调用它。C#.NET程序语言中我们把这个单独的单元叫做函数函数的特点函数拥有自己的名称,可以使用合法的C#.NET标识符来命名。但其名称不能与变量、常数或定义在类内的属性或者其他方法名重复。函数内声明的变量属于局部变量,也就是说C#.NET在不同函数内声明的变量彼此互不相关,其作用域局限在该函数内。所以在不同的函数内允许声明相同局部变量名称。函数有特定功能,程序代码简单明确,可读性高而且容易调试和维护。5.1函数的定义和使用函数就是代码的逻辑片断,它可以执行特定的操作。对象或者类调用函数来实现函数的功能。函数可以有返回类型,当然,返回类型也可以是Void。函数声明的语法为:修饰符返回类型函数名称(参数1,参数2,…)函数的修饰符函数的修饰符有很多,如:newpublicprotectedinternalprivatestaticvirtualsealedoverrideabstractextern函数修饰符的含义上面诸多函数修饰符中,Public、Protected、Internal、ProtectedInternal、Private是对函数作用域的修饰,其余的关键字有其他的含义,在此,我们只讲函数作用域修饰符的意义。函数修饰符的含义一个简单的调用函数的例子声明函数之后,我们就可以调用任何类或者对象所使用的函数。例:第一个函数的定义以及调用usingSystem;usingSystem.Collections.Generic;usingSystem.Text;namespaceExample1Of5{classProgram{staticvoidMain(string[]args){Console.WriteLine(输入你的大名:);strings=Console.ReadLine();myFirstMethod(s);}staticvoidmyFirstMethod(strings1){Console.WriteLine(Welcome+s1+,Youhaveenteredtheworldofthemethod!);}}}程序运行结果5.2函数参数的传递方式在调用函数的时候,可以向函数传递参数列表。C#中函数的参数有4种类型:值参数,不含任何修饰符。引用型参数,以Ref修饰符声明。输出参数,以Out修饰符声明。数组型参数,以Params修饰符声明。若A语句中调用函数B,两者间有参数传递,那么,我们将A调用语句中传送的参数称为实参;被调用的函数B中使用的参数成为形参。5.2.1值参数当利用值向函数传递参数时,编译程序给实参的值做一份复制,并且将此复制传递给该函数。被调用的函数不会修改内存中实参的值,所以使用值参数时,可以保证实际值是安全的。值参数传递示例例值参数传递示例。程序代码:usingSystem;namespaceExample3Of5{classProgram{staticvoidMain(string[]args){inta=3;intb=5;change(a,b);Console.WriteLine(a={0},b={1},a,b);}staticvoidchange(inta1,intb1){intt;t=a1;a1=b1;b1=t;}}}程序运行结果此程序的输出结果是a=3,b=5,可见我们并没有达到交换的目的,在这个程序里我们采用了值参数传递,形参值的修改并不影响实参的值。5.2.2引用型参数与值参不同的是,引用型参数并不开辟新的内存区域。当利用引用型参数向函数传递形参时,编译程序将把实际值在内存中的地址传递给函数。在函数中,引用型参数通常已经初始化。引用型参数传递例子例把上面例子改写成引用型参数传递。程序代码:usingSystem;namespaceExample4Of5{classProgram{staticvoidMain(string[]args){inta=3;intb=5;change(refa,refb);Console.WriteLine(a={0},b={1},a,b);}staticvoidchange(refinta1,refintb1){intt;t=a1;a1=b1;b1=t;}}}运行结果及分析此程序的输出结果是a=5,b=3。在Main()函数中,调用了change函数,使用引用型参数,成功地实现了a和b的交换。a1和b1所处的内存区域其实就是a和b所处的内存区域,所以当a1和b1的值互换时,a和b的值自然会发生变化。5.2.3输出型参数与引用型参数类似,输出型参数也不开辟新的内存区域。与引用型参数的差别在于,调用前不需对变量进行初始化。输出型参数用于传递方法返回的数据。Out修饰符后应跟随与形参的类型相同的类型声明。在方法返回后,传递的变量被认为经过了初始化。Out关键字使用小例子例使用Out关键字练习编写输出参数。程序代码:usingSystem;namespaceExample5Of5{classProgram{staticvoidMain(string[]args){Console.WriteLine(\nout参数输出****\n);inta,b;UseOut(outa,outb);Console.WriteLine(\n调用UseOut函数后返回主程序:a={0},b={1},a,b);Console.ReadLine();}privatestaticvoidUseOut(outintx,outinty){inttemp;x=20;y=30;Console.WriteLine(\n函数内交换前x={0},y={1},x,y);temp=x;x=y;y=temp;Console.WriteLine(\n函数内交换后x={0},y={1},x,y);}}}运行结果5.2.4数组型参数C#允许为函数指定一个(只能指定一个)特定的参数,这个参数必须是函数定义中的最后一个参数,称为数组型参数。数组型参数可以使用个数不定的参数调用函数,它可以使用params关键字来定义。另外,参数只允许是一维数组。比如int[]和int[][]类型都可以作为数组型参数,而int[,]则不可以。最后,数组型参数不能再有Ref和Out修饰符。数组型参数示例例数组型参数示例usingSystem;namespaceExample6Of5{classProgram{staticvoidMain(string[]args){intmaxAge=Max(18,23,19,22,27);Console.WriteLine(themaxofageis:{0},maxAge);}staticintMax(paramsint[]Age){inttemp=0;for(inti=0;iAge.Length;i++){if(tempAge[i])temp=Age[i];}returntemp;}}}程序运行结果数组型参数示例例数组型参数示例(多种类型的实参,同一形参)。程序代码:usingSystem;namespaceExample7Of5{classProgram{staticvoidMain(string[]args){int[]f1={1,2,3,4};Output(f1);Output(10,20,30);Output();Console.ReadLine();}staticvoidOutput(paramsint[]a){Console.WriteLine(thereare{0}elements:,a.Length);foreach(intiina){Console.Write({0},,i);}Console.WriteLine();}}}程序运行结果5.2.5参数的匹配在调用函数时,实参和形参必须完全匹配,这意味着形参与实参之间类型、个数和顺序都要完全匹配。例如下面的函数:privatevoidf(inta,stringb){Console.WriteLine(dsahfsd;hnf);}则不能使用下面的代码调用;f(1,2);这是因为,函数的形参第一个为整型,第二个为string型。而调用函数的代码中第一个实参为整型,第二个还是整型,与函数的第二个形参不匹配。同样,上面的函数也不能被以下代码调用:f(there);这里的实参形参个数明显不一样,所以不可以。参数的不匹配通不过编译,因为编译器要求必须匹配函数的签名。5.3区块变量与属性成员5.3.1区块变量C#.NET语言中,区块变量被定义于某个区块中,比如说前面所讲的While循环语句中声明的变量,只能在所定义的While循环中使用。也就是说,某区块中定义的变量,只能供这个区块使用,区块以外使用则报错。5.3.2属性成员属性成员跟在第二章中介绍的静态变量一样,不同的是对象属性是放在堆里面的,必须对对象进行实例化,才可以使用属性;而静态字段是放在全局变量区的,不需要实例化对象就直接可以引用静态变量。classtest{publicstaticintvalue;//静态变量publicintvalue1;//对象属性}5.4Main()函数所有的C#应用程序必须在它的一个类中定义一个名为Main的函数。这个函数作为应用程序的入口点,它必须被定义为静态的。具体在哪个类中使用Main()函数对C#编译器并无影响,而且你选择的类也不影响编译的次序。这与C++不同,在C++中编译应用程序时必须密切注意依赖性。C#编译器很精明,可以自己在源代码文件中自动搜寻到Main()函数。因此,这个最重要的方法是所有C#应用程序的入口点。虽然一个C#应用中可能会有很多类,但是其中只有一个入口。在同一个应用中,可能多个类都有Main()函数,但是只有一个Main()函数是被执行的。你需要在编译的时候指定究竟使用哪一个Main()函数。常见的Main()函数是这样的:staticvoidMain(string[]args){}Main()函数中的参数Args是从应用程序的外部接受信息的方法,这些信息在运行期间指定,其形式是命令行参数。细心的读者会注意到,Main()函数必须定义为静态的,这是因为C#.NET是一门真正的面向对象的编程语言,Main()函数是整个应用程序的入口,Static可以保证程序调用的时候不需要实例化就可以运行程序。看看下面的一段代码:namespacetest{classTest{publicvoidInstanceMethod(){}//实例成员(非静态)publicstaticvoidStaticMethod{}//类型成员(静态)staticvoidMain(string[]args){InstanceMethod();//错误!调用了实例成员,而此时并没有建立实例StaticMethod();//正确!可以调用静态成员TestSomeTest=newTest();//建立本类型的一个实例SomeTest.InstanceMethod();//再在这个实例上调用实例成员就对了SomeTest.StaticMethod();/
本文标题:C#课程教学5
链接地址:https://www.777doc.com/doc-3931138 .html