第03章(C#教程)

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

第3章对象和类型到目前为止,我们介绍了组成C#语言的主要内容——变量的声明、数据类型和程序流语句,并简要介绍了一个只包含Main()方法的完整小例子。但还没有介绍如何把这些内容组合在一起,构成一个完整的程序,其关键就在于对类的处理。这就是本章的主题。本章的主要内容如下:●类和结构的区别●字段、属性和方法●按值和引用传送参数●方法重载●构造函数和静态构造函数●只读字段●Object类,其他类型都从该类派生而来第4章将介绍继承以及与继承相关的特性。提示:本章将讨论与类相关的基本语法,但假定您已经熟悉了使用类的基本原则,例如,知道构造函数和属性的含义,因此我们只是大致论述如何把这些原则应用于C#代码。如果您不熟悉类的概念,请参阅附录A,并可从网站上下载本书的代码。本章介绍的这些概念不一定得到了大多数面向对象语言的支持。例如对象构造函数是您熟悉的、使用广泛的一个概念,但静态构造函数就是C#的新增内容,所以我们将解释静态构造函数的工作原理。3.1类和结构类和结构实际上都是创建对象的模板,每个对象都包含数据,并提供了处理和访问数据的方法。类定义了每个类对象(称为实例)可以包含什么数据和功能。例如,如果一个类表示一个顾客,就可以定义字段CustomerID、FirstName、LastName和Address,以包含该顾客的信息。还可以定义处理存储在这些字段中的数据的功能。接着,就可以实例化这个类的对象,以表示某个顾客,并为这个实例设置这些字段,使用其功能。classPhoneCustomer{publicconststringDayOfSendingBill=Monday;publicintCustomerID;publicstringFirstName;第3章对象和类型•71•publicstringLastName;}结构在内存中的存储方式(类是存储在堆(heap)上的引用类型,而结构是存储在堆栈(stack)上的值类型)、访问方式和一些特征(如结构不支持继承)与类不同。较小的数据类型使用结构可提高性能。但在语法上,结构与类非常相似,主要的区别是使用关键字struct代替class来声明结构。例如,如果希望所有的PhoneCustomer实例都存储在堆栈上,而不是存储在托管堆上,就可以编写下面的语句:structPhoneCustomerStruct{publicconststringDayOfSendingBill=Monday;publicintCustomerID;publicstringFirstName;publicstringLastName;}对于类和结构,都使用关键字new来声明实例:这个关键字创建对象并对其进行初始化。在下面的例子中,类和结构的字段值都默认为0:PhoneCustomermyCustomer=newPhoneCustomer();//worksforaclassPhoneCustomerStructmyCustomer2=newPhoneCustomerStruct();//worksforastruct在大多数情况下,类要比结构常用得多。因此,我们先讨论类,然后指出类和结构的区别,以及选择使用结构而不使用类的特殊原因。但除非特别说明,否则就可以假定用于类的代码也适用于结构。3.2类成员类中的数据和函数称为类的成员。Microsoft的正式术语对数据成员和函数成员进行了区分。除了这些成员外,类还可以包含嵌套的类型(例如其他类)。类中的所有成员都可以声明为public(此时可以在类的外部直接访问它们)或private(此时,它们只能由类中的其他代码来访问)。与VB、C++和Java一样,C#在这个方面还有变化,例如protected(表示成员仅能由该成员所在的类及其派生类访问),第4章将详细解释各种访问级别。3.2.1数据成员数据成员包含了类的数据——字段、常量和事件。数据成员可以是静态数据(与整个类相关)或实例数据(类的每个实例都有它自己的数据副本)。通常,对于面向对象的语言,类成员总是实例成员,除非用static进行了显式的声明。字段是与类相关的变量。在前面的例子中已经使用了PhoneCustomer类中的字段:一旦实例化PhoneCustomer对象后,就可以使用语法Object.FieldName来访问这些字段:PhoneCustomerCustomer1=newPhoneCustomer();C#高级编程(第3版)•72•Customer1.FirstName=Simon;常量与类的关联方式同变量与类的关联方式一样。使用const关键字来声明常量。如果它们声明为public,就可以在类的外部访问。classPhoneCustomer{publicconststringDayOfSendingBill=Monday;publicintCustomerID;publicstringFirstName;publicstringLastName;}事件是类的成员,它可以让对象将某些特定行为(例如改变类的字段或属性,或者进行了某种形式的用户交互操作)发生的时间告知调用程序。客户可以包含一些称为事件处理程序的代码来响应该事件。第6章将详细介绍事件。3.2.2函数成员函数成员提供了操作类中数据的某些功能,包括方法、属性、构造函数和终结器(finalizor)、运算符以及索引器。方法是与某个特定类相关的函数,它们可以是实例方法,也可以是静态方法。实例方法处理类的特定实例,静态方法提供了更一般的功能,不需要实例化一个类(例如前面的Console.WriteLine()方法)。下一节介绍方法。属性是与在客户机上用与访问类的公共字段类似的方式访问的函数。C#为读写类上的属性提供了专用语法,所以不必使用那些名称中嵌有Get或Set的偷工减料的方法。因为属性的这种语法不同于一般函数的语法,在客户代码中,虚拟的对象被当做实际的东西。构造函数是在实例化对象时自动调用的函数。它们必须与所属的类同名,且不能有返回类型。构造函数可用于在实例化对象时设置字段的值。终结器类似于构造函数,但是在CLR检测到不再需要某个对象时调用。它们的名称与类相同,但前面有一个~符号。C++程序员应注意,终结器在C#中比在C++中用得较少一些,因为CLR会自动进行垃圾收集,另外,不可能预测什么时候调用析构函数。第7章将介绍终结器。运算符执行的最简单的操作就是+和–。在对两个整数进行相加操作时,严格地说,就是对整数使用+运算符。C#还允许指定把已有的运算符应用于自己的类(运算符重载)。第5章将详细论述运算符。索引器允许对象以数组或集合的方式进行索引。第5章介绍索引器。1.方法在VB、C和C++中,可以定义与某个特定类完全不相关的全局函数,但在C#中不能这样做。在C#中,每个函数都必须与一个类或结构相关。注意,正式的C#术语实际上并没有区分函数和方法。在这个术语中,“函数”不仅包含方法,而且也包含类或结构的一些非数据成员。它包括索引器、运算符、构造函数和析构函数等,第3章对象和类型•73•甚至还有属性。这些都不是数据成员,字段、常量和事件才是数据成员。本章将详细讨论方法。(1)方法的声明在C#中,定义方法的语法与C风格的语言相同,与C++和Java中的语法也相同。与C++的主要语法区别是,在C#中,每个方法都单独声明为public或private,不能使用public:块把几个方法定义组合起来。另外,所有的C#方法都在类定义中声明和定义。在C#中,不能像在C++中那样把方法的实现代码分隔开来。在C#中,方法的定义包括方法的修饰符(例如方法的可访问性)、返回值的类型,然后是方法名、输入参数的列表(用圆括号括起来)和方法体(用花括号括起来)。[modifiers]return_typeMethodName([parameters]){//Methodbody}每个参数都包括参数类型名及在方法体中的引用名称。但如果方法有返回值,return语句就必须与返回值一起使用,指定出口点,例如:publicboolIsSquare(Rectanglerect){return(rect.Height==rect.Width);}这段代码使用一个表示矩形的.NET基类System.Drawing.Rectangle。如果方法没有返回值,就把返回类型指定为void,因为不能省略返回类型。如果方法不带参数,仍需要在方法名的后面写上一对空的圆括号()(就像本章前面的Main()方法)。此时还包含一个可选的return语句——当到达右花括号时,方法会自动返回。注意方法可以包含任意多个return语句:publicboolIsPositive(intvalue){if(value0)returnfalse;returntrue;}(2)调用方法C#中调用方法的语法与C++和Java中的一样,C#和VB的惟一区别是在C#中调用方法时,必须使用圆括号,这要比VB6中有时需要括号,有时不需要括号的规则简单一些。下面的例子MathTest说明了类的定义和实例化、方法的定义和调用的语法。除了包含Main()方法的类之外,它还定义了类MathTest,该类包含两个方法和一个字段。C#高级编程(第3版)•74•usingSystem;namespaceWrox.ProCSharp.MathTestSample{classMainEntryPoint{staticvoidMain(){//TrycallingsomestaticfunctionsConsole.WriteLine(Piis+MathTest.GetPi());intx=MathTest.GetSquareOf(5);Console.WriteLine(Squareof5is+x);//InstantiateatMathTestobjectMathTestmath=newMathTest();//thisisC#'swayof//instantiatingareferencetype//Callnon-staticmethodsmath.value=30;Console.WriteLine(Valuefieldofmathvariablecontains+math.value);Console.WriteLine(Squareof30is+math.GetSquare());}}//DefineaclassnamedMathTestonwhichwewillcallamethodclassMathTest{publicintvalue;publicintGetSquare(){returnvalue*value;}publicstaticintGetSquareOf(intx){returnx*x;}publicstaticdoubleGetPi(){return3.14159;}}}第3章对象和类型•75•运行mathTest示例,会得到如下结果:cscMathTest.csMicrosoft(R)VisualC#.NETCompilerversion7.10.3052.4forMicrosoft(R).NETFrameworkversion1.1.4322Copyright(C)MicrosoftCorporation2001-2002.Allrightsreserved.MathTestPiis3.14159Squareof5is25Valuefieldofmathvariablecontains30Squareof30is900从代码中可以看出,MathTest类包含一个字段和一个方法,该字段包含一个数字,该方法计算数字的平方。这个类还包含两个静态方法,返回pi的值,并把数字的平方作为参数传入。这个类有一些功能并不是C#程序设计的好例子。例如,GetPi()通常作为const字段来执行,而好的设计应使用目前还没有介绍的概念。C++和Java开发人员应很熟悉这个语法的大多数内容。如果您

1 / 24
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功