资源描述
,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,第,5,章函数、域与属性,计算机科学系,毕好昌,2011,年,3,月,主要内容,函数的定义、使用,属性与域的定义以及使用,C#,中函数的定义,在大多数的应用软件的设计中,将应用程序分成若干个功能单元。由于小段的程序更易于理解、设计、开发和调试,因此采用功能单元是应用程序设计的核心法则。分为若干个功能单元以便在应用程序中重用功能构件。另外,在整个大的程序中,某些任务常常要在一个程序中运行好多次,举个最简单的例子,对多个数组进行排序。此时我们就可以把这些相同的代码段写成一个单独的单元,需要的时候我们就来调用它。,C#.NET,程序语言中我们把这个单独的单元叫做函数,函数的特点,函数拥有自己的名称,可以使用合法的,C#.NET,标识符来命名。但其名称不能与变量、常数或定义在类内的属性或者其他方法名重复。,函数内声明的变量属于局部变量,也就是说,C#.NET,在不同函数内声明的变量彼此互不相关,其作用域局限在该函数内。所以在不同的函数内允许声明相同局部变量名称。,函数有特定功能,程序代码简单明确,可读性高而且容易调试和维护。,5.1,函数的定义和使用,函数就是代码的逻辑片断,它可以执行特定的操作。对象或者类调用函数来实现函数的功能。函数可以有返回类型,当然,返回类型也可以是,Void,。,函数声明的语法为:,(,参数,1,,参数,2,,,),函数的修饰符,函数的修饰符有很多,如:,new,public,protected,internal,private,static,virtual,sealed,override,abstract,extern,函数修饰符的含义,上面诸多函数修饰符中,,Public,、,Protected,、,Internal,、,Protected Internal,、,Private,是对函数作用域的修饰,其余的关键字有其他的含义,在此,我们只讲函数作用域修饰符的意义。,函数修饰符的含义,一个简单的调用函数的例子,声明函数之后,我们就可以调用任何类或者对象所使用的函数。,例:第一个函数的定义以及调用,using System;,using,System.Collections.Generic,;,using,System.Text,;,namespace Example1Of5,class Program,static void,Main(string,args,),Console.WriteLine,(,输入你的大名:,);,string s=,Console.ReadLine,();,myFirstMethod(s,);,static void,myFirstMethod(string,s1),Console.WriteLine(Welcome,+s1+,You have entered the world of the method!);,程序运行结果,5.2,函数参数的传递方式,在调用函数的时候,可以向函数传递参数列表。,C#,中函数的参数有,4,种类型:,值参数,不含任何修饰符。,引用型参数,以,Ref,修饰符声明。,输出参数,以,Out,修饰符声明。,数组型参数,以,Params,修饰符声明。,若,A,语句中调用函数,B,,两者间有参数传递,那么,我们将,A,调用语句中传送的参数称为实参;被调用的函数,B,中使用的参数成为形参。,5.2.1,值参数,当利用值向函数传递参数时,编译程序给实参的值做一份复制,并且将此复制传递给该函数。被调用的函数不会修改内存中实参的值,所以使用值参数时,可以保证实际值是安全的。,值参数传递示例,例,值参数传递示例。,程序代码:,using System;,namespace Example3Of5,class Program,static void,Main(string,args,),int,a=3;,int,b=5;,change(a,b,);,Console.WriteLine(a,=0,b=1,a,b);,static void,change(int,a1,int,b1),int,t;,t=a1;,a1=b1;,b1=t;,程序运行结果,此程序的输出结果是,a=3,,,b=5,,可见我们并没有达到交换的目的,在这个程序里我们采用了值参数传递,形参值的修改并不影响实参的值。,5.2.2,引用型参数,与值参不同的是,引用型参数并不开辟新的内存区域。当利用引用型参数向函数传递形参时,编译程序将把实际值在内存中的地址传递给函数。,在函数中,引用型参数通常已经初始化。,引用型参数传递例子,例,把上面例子改写成引用型参数传递。,程序代码:,using System;,namespace Example4Of5,class Program,static void,Main(string,args,),int,a=3;,int,b=5;,change(ref,a,ref b);,Console.WriteLine(a,=0,b=1,a,b);,static void,change(ref,int,a1,ref,int,b1),int,t;,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,关键字练习编写输出参数。,程序代码:,using System;,namespace Example5Of5,class Program,static void,Main(string,args,),Console.WriteLine(n,out,参数输出 *,n);,int,a,b;,UseOut(out,a,out,b);,Console.WriteLine(n,调用,UseOut,函数后返回主程序:,a=0,b=1,a,b);,Console.ReadLine,();,private static void,UseOut(out,int,x,out,int,y),int,temp;,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,修饰符。,数组型参数示例,例,数组型参数示例,using System;,namespace Example6Of5,class Program,static void,Main(string,args,),int,maxAge,=Max(18,23,19,22,27);,Console.WriteLine(the,max of age is:0,maxAge);,static,int,Max(params,int,Age),int,temp=0;,for(,int,i=0;i,Age.Length,;i+),if(temp,Agei,),temp=,Agei,;,return temp;,程序运行结果,数组型参数示例,例,数组型参数示例(多种类型的实参,同一形参)。,程序代码:,using System;,namespace Example7Of5,class Program,static void,Main(string,args,),int,f1=1,2,3,4;,Output(f1);,Output(10,20,30);,Output();,Console.ReadLine,();,static void,Output(params,int,a),Console.WriteLine(there,are 0,elements:,a.Length,);,foreach,(,int,i in a),Console.Write(0,i);,Console.WriteLine,();,程序运行结果,5.2.5,参数的匹配,在调用函数时,实参和形参必须完全匹配,这意味着形参与实参之间类型、个数和顺序都要完全匹配。例如下面的函数:,private void,f(int,a,string,b),Console.WriteLine(dsahfsd;hnf,);,则不能使用下面的代码调用,;,f(1,2);,这是因为,函数的形参第一个为整型,第二个为,string,型。而调用函数的代码中第一个实参为整型,第二个还是整型,与函数的第二个形参不匹配。,同样,上面的函数也不能被以下代码调用:,f(there,);,这里的实参形参个数明显不一样,所以不可以。,参数的不匹配通不过编译,因为编译器要求必须匹配函数的签名。,5.3,区块变量与属性成员,5.3.1,区块变量,C#.NET,语言中,区块变量被定义于某个区块中,比如说前面所讲的,While,循环语句中声明的变量,只能在所定义的,While,循环中使用。也就是说,某区块中定义的变量,只能供这个区块使用,区块以外使用则报错。,5.3.2,属性成员,属性成员跟在第二章中介绍的静态变量一样,不同的是对象属性是放在堆里面的,必须对对象进行实例化,才可以使用属性;而静态字段是放在全局变量区的,不需要实例化对象就直接可以引用静态变量。,class test,public static,int,value;/,静态变量,public,int,value1;/,对象属性,5.4,Main(),函数,所有的,C#,应用程序必须在它的一个类中定义一个名为,Main,的函数。这个函数作为应用程序的入口点,它必须被定义为静态的。具体在哪个类中使用,Main(),函数对,C#,编译器并无影响,而且你选择的类也不影响编译的次序。这与,C+,不同,在,C+,中编译应用程序时必须密切注意依赖性。,C#,编译器很精明,可以自己在源代码文件中自动搜寻到,Main,()函数。因此,这个最重要的方法是所有,C#,应用程序的入口点。,虽然一个,C#,应用中可能会有很多类,但是其中只有一个入口。在同一个应用中,可能多个类都有,Main(),函数,但是只有一个,Main,()函数是被执行的。你需要在编译的时候指定究竟使用哪一个,Main(),函数。,常见的,Main(),函数是这样的:,static void,Main(string,args,),Main(),函数中的参数,Args,是从应用程序的外部接受信息的方法,这些信息在运行期间指定,其形式是命令行参数。,细心的读者会注意到,,Main(),函数必须定义为静态的,这是因为,C#.NET,是一门真正的面向对象的编程语言,,Main(),函数是整个应用程序的入口,,Static,可以保证程序调用的时候不需要实例化就可以运行程序。,看看下面的一段代码:,namespace test,class Test,public void,InstanceMethod,()/,实例成员(非静态),pu
展开阅读全文