C#面向对象讲义.pdf
第3章 面向对象的程序设计 3.1 面向对象程序(OOP)设计概述3.1.1 面向过程与面向对象程序设计3.1.1.1 面向过程的程序设计面向过程的程序设计是基于过程的语言(如 C)常用的一种编程方法。它主要是强调把整个系统划分为细小的功能模块,称为过程,每个过程用以实现不同的功能,使用的时候按预定的步骤调用就可以了。同时,还要编写一个具有程序入口功能的主程序,当运行一个软件时,主程序会先运行,并按照用户的需要调用其他过程,直到程序运行结束。由此可见,面向过程的程序的执行方式是过程驱动或步骤驱动。当完成一个程序设计后,如果程序的功能变了,就必须修改程序或重新设计程序,因此,面向过程的程序设计方式代码重用率很低,不便于维护。面向过程程序设计模式:例如:开发五子棋游戏软件,面向过程的设计思路就是首先分析问题的步骤:开始游戏绘制画面黑子下棋绘制画面判断输赢白子下棋绘制画面判断输赢返回步骤输出最后结果把上面每个步骤用分别的函数来实现,问题就解决了。存在着如下缺陷:(1)以过程(功能)为单位,不能和现实世界很直观地映射,不易于理解。(2)程序的定律是:程序=(算法)+(数据结构),而传统的程序设计方法是算法和数据分离的。(3)面向功能的分解,而用户的改变绝大多数是面向功能的改变,功能实现分散在各过程中,不易于维护和功能扩展。(4)数据结构与算法分离,不利于信息隐臧。如下棋规则变了,必须修改与规则相关的各过程,再比如要加入悔棋功能,那么从输入到判断到显示这一连串的步骤都要改动。3.1.1.2 面向对象程序设计面向对象的程序设计O O P (O b j e c t O r i e n t e d P r o g r a m m i n g)是在面向过程的基础上发展起来的一种新的程序设计思想。在面向对象的程序设计中,将系统分成若干个功能实体,称为对象,对象是构成程序的基本单位和运行实体。每一个对象都有自己的数据和行为,它们均被封装在对象内部,通过这样若干个对象的相互作用来实现程序设计的设计目标。同样分析五子棋游戏,只需为该系统创建以下几类对象:(1)黑白双方对象:这两种对象除了颜色不一样外,其余的数据和行为都是一模一样的。(2)棋盘对象:负责绘制画面。(3)规则对象:负责判定诸如犯规、输赢等。当程序运行时,第一类对象(黑白双方对象)负责接受用户输入,并告知第二类对象(棋盘对象)棋子布局的变化,棋盘对象接收到了棋子的变化就要负责在屏幕上面显示出这种变化,同时利用第三类对象(规则系统)来对棋局进行判定。可以看出,这种思想方式,完全与现实世界相吻合。面向对象程序设计模式:面向过程的程序的执行路线是代码事先确定好的,而面向对象的程序的执行则是由事件驱动实现的,也就是说完全取决于用户在使用程序时激活了什么事件,这种程序执行方式叫事件驱动方式。演示学生公寓管理系统,理解事件驱动。3.1.2面向对象程序设计的基本概念3.1.2.1 抽象(Abstract)从许多事物中舍弃个别的、非本质的特征,抽取共同的、本质性的特征,就叫做抽象。抽象是形成概念的必须手段。抽象原则有两方面的意义:第一,尽管问题域中的事物是很复杂的,但是分析员并不需要了解和描述它们的一切,只需要分析研究其中与系统目标有关的事物及其本质性特征。第二,通过舍弃个体事物在细节上的差异,抽取其共同特征而得到一批事物的抽象概念。抽象是面向对象方法中使用最为广泛的原则。抽象原则包括过程抽象和数据抽象两个方面。过程抽象是指,任何一个完成确定功能的操作序列,其使用者都可以把它看做一个单一的实体,尽管实际上它可能是由一系列更低级的操作完成的。数据抽象是指根据施加于数据之上的操作来定义数据类型,并限定数据的值只能由这些操作来修改和观察。数据抽象是面向对象分析的核心原则。它强调把数据(属性)和 操 作(服务)结合为一个不可分的系统单位(即类),类的外部只需要知道它能做什么,而不必知道它如何做。3.1.2.2 对象(Object)对象是面向对象程序设计的基础,有时也称为实例,它有自己的成员和特征,对象是运行期的基本实体。如一个按钮,一个标签等都是对象。3.1.2.3 类(Class)类是对同类对象的抽象,通过类我们可以创建若干个对象,我们可以认为类是对某类实体的综合描述和定义,而对象是一个确确实实的个体。类是一组具有相同数据结构和相同操作的对象的集合,是对一系列具有相同性质的对象的抽象,是对对象的共同特征的描述。如:图 纸(类)如汽车就是一个类,而某辆具体的汽车就是该类的一个实例,称为对象。3.1.2.4 封装(Encapsulation)封装是面向对象技术的一个重要原则,把数据和函数及其服务包装在一个单独的单元(称为类)的行为称为封装。它尽可能的隐蔽对象的内部细节,而外部只能通过接口与之发生联系。面向对象编程的封装性原则要求不能直接访问类中的数据成员。这主要是因为:一如果直接访问类的数据成员,就必须充分了解类的实现细节,这有悖于隐藏设计细节的思想,会限制代码的重用性和维护性。一如果直接访问类的数据成员,就可能有意或无意地破坏对象中的数据,可能会导致难以调试的程序缺陷。3.1.2.5 继承(Inheritance)继承是可以让某个类型的对象获得另个类型的对象的属性的方法。如:在 OOP中,继承的概念很好的支持了代码的重用性。3.1.2.6 重载(Overload)重载是指让同名的方法或运算符具有不同功能,可以根据不同的参数执行不同的功能。重载包含方法重载和运算符重载两大类。函数重载:函数名一样,参数的个数或者类型不一样;如让max函数既可以求数值型数据的最大值,也可以求字符串型数据的最大值:让十运算符即可以求实数的和,也可以求复数的和等。3.1.2.7 多态性(Polymorphism)多态是OOP的另一个重要概念。多态的意思是事物具有不同形式的能力,即多种形态。方法的市我和抽象类都是多态的表现。如:多态机制使具有不同内部结构的对象可以共享相同的外部接口。这意味着,虽然针对不同对象的具体操作不同,但通过一个公共的类,它 们(那些操作)可以通过相同的方式予以调用。多态在实现继承的过程中被广泛应用。因此面向对象程序设计的特性有:抽象一封装f继承f多 态(有严格的时序性)3.2 类与对象在 c#中,使用类之前应先定义类,再根据类生成实例一一对象,一个c#程序至少应包含一个类。3.2.1 类的声明格式:m o d if ie r s c l a s s id e n t if ie r :b a s e-l is t c l a s s-b o d y ;说明:1、m o d if ie r s:修饰符,C#中的修饰符有n e w、a b s t r a c t s e a l e d 和四个访问修饰符:p u b l ic,p r o t e c t e d in t e r n a l,p r iv a t e in t e r n a l 等。在 C#中类可以嵌套定义,最外层的类称为顶级类。适应于顶级类的修饰符人有:a b s t r a c t,s e a l e d,p u b l ic 和 in t e r n a l,默认的类修饰符为in t e r n a lo(1)a b s t r a c t :抽象类或不完整类,该类只能是其他类的基类。(2)s e a l e d:密封类,不能被继承。将密封类用作基类是错误的。在类声明中使用s e a l e d 修饰符可防止继承此类。s e a l e d 和 a b s t r a c t 不能同时施加在同一个类前。(3)in t e r n a l 关键字是类和类成员的访问修饰符。只有在同一程序集的文件中,内部类或成员才是可访问的2、id e n t if ie r:类名3、b a s e-l is t:即该类继承的基类和多个接口的列表,各项之间由逗号分隔。4、c l a s s-b o d y:类成员的声明。3.2.2对象的声明格式:类名对象名=n e w类名(参数);或分成两步:类名对象名:对象名=n e w类名(参数);例:u s in g Sy s t e m;c l a s s s t u d e n tp r iv a t e s t r in g n o;p r iv a t e s t r in g n a m e;p r iv a t e in t a g e;p r iv a t e c h a r s e x;p r iv a t e d o u b l e a v e r;p u b l ic s t u d e n t (s t r in g s n o,s t r in g s n a m e,in t s a g e,c h a r s s e x,d o u b l e s a v e r)/构造函数n o=s n o;n a m e=s n a m e;a g e=s a g e;s e x=s s e x;a v e r=s a v e r;)p u b l ic v o id d is p s t u d e n t ()Co n s o l e.Wr it e Lin e(学号:0 姓名:年龄:性别:平均成绩:,n o,n a m e,a g e,s e x,a v e r);s t a t ic v o id Ma in()(s t u d e n t s i,s 2;s l=n e w s t u d e n t (“10 1,张三,20,男,88);相当于 s t u d e n t s i=n e ws t u d e n t ();s i.d is p s t u d e n t ();s 2=n e w s t u d e n t (“10 2,李四,19,女,90);s 2.d is p s t u d e n t ();)3.2.3类的成员3.2.3.1 成员分类类的成员可以是本类中直接声明的成员,或者从它的基类中继承来的成员。类中的成员可以有:成员含义常量(Co n s t a n t)表示个和类相关的常量值字段(F ie l d s)表示类中的变量方法(Me t h o d s)用来实现计算和类的功能属性(p r o p e r t ie s)定义个类的属性,通过读和写操作这个属性事件(E v e n t s)定义一个类产生的动作索引(I n d e x e r s)允许类的实例像访问数组样被访问操作符(O p e r a t o r s)定义一个可以被类的实例使用的操作符号构造函数(I n s t a n c e Co n s t r u c t o r s)初始化类的实例,在创建类实例时被自动执行析构函数(De s t r u c t o r s)在类被d e s t o r y 之前自动调用析构函数,静态构造函数(St at i c C o n s t r u c t o r s)在初始化类本身的时候使用类型(Ty p e)代表类内部的类型3.2.3.2 类成员的可访问性通过权限修饰符指定声明的类型和类型成员的可访问性。主要有以下几种:(1)公 有(Pu b l i c):成员对于任何人都是可见的,访问不受限制(2)私 有(Pr i v at e):成员是隐藏的,只有对类本身是可用的,不能被继承。(3)受 保 护(Pr o t e c t e d):成员和私有成员类似,只能由包含它的类或其派生类访问,这样既可以方便派生类使用,又可以对外界隐藏。(4)内部(I n t e r n al):成员对整个应用程序是公有的,但对于其他的外部应用程序是私有的。当我们希望其他应用程序能够使用当前应用程序中的包含的一个类,但又希望这个类为当前应用程序保留一定的功能时,就要用到内部。(5)受保护内部(Pr o t e c t e d I n t e r n al):成员只能由包含了基类的应用程序中的从该基类派生的子类所访问。类成员的默认修饰符是p r i v at e。3.2.3.3静态和实例成员对类中的成员,要么是静态成员,要么是实例成员。静态成员:是指用s t at i c 修饰符声明的成员,静态成员的访问方式为:类名.成员名,不需要实例化便可引用。一个静态字段只指明了一个存储位置,无论有多少个实例被创建,静态字段还是只有一个,而不会产生多个。注意:若在本类中访问静态成员,类名可以省略。实例成员:或称非静态成员,指没用s t at i c 修饰符声明的成员。每次类实例化的时候,就创建所有的新的实例字段。例 1:此例说明了静态成员和非静态成员的访问方法。u s i n g Sy s t e m;c l as s C l as s ip u b l i c i n t x;定义非静态字段xp u b l i c s t at i c i n t y;定义静态字段 yp u b l i c v o i d f l ()定义非静态方法f l ()C o n s o l e.W r i t e L i n e(z,f 1 i s a i n s t an c e m e t h o d!”);)p u b l i c s t at i c v o i d f 2()定义静态方法 f 2()(C o n s o l e.W r i t e L i n e(z,f 1 i s a s t at i c m e t h o d!/z);)c l as s C l as s 2(s t at i c v o i d M ai n OC l as s i o b j o f c l as s l =n e w C l as s i();o b j o f c l as s l.x =1 0 0;C l as s i.y =20 0;C o n s o l e.W r i t e L i n e(/,x=0 ,y二1 ,o b j o f c l as s l.x,C l as s i,y);o b j o f c l as s l.f l();C l as s i.f 2();)用 string类中的Format方法和Insert方法加以说明。例 2:此例说明了静态成员与动态成员的区别。u s i n g Sy s t e m;c l as s C l as s A(p u b l i c i n t x=l;p u b l i c s t at i c i n t y=l;p u b l i c C l as s A()x+;y+;)定义构造函数c l as s C l as s Bs t at i c v o i d M ai n()(C l as s A m y c l as s l=n e w C l as s A();C o n s o l e.W r i t e L i n e(m y c l as s i.x);C o n s o l e.W r i t e L i n e(C l as s A.y);C l as s A m y c l as s 2=n e w C l as s A ();C o n s o l e.W r i t e L i n e(m y c l as s 2.x);C o n s o l e.W r i t e L i n e(C l as s A.y);C l as s A m y c l as s 3=n e w C l as s A ();C o n s o l e.W r i t e L i n e(m y c l as s 3.x);C o n s o l e.W r i t e L i n e(C l as s A.y);创建第一个实例静态成员不用实例化便可引用创建第二个实例创建第三个实例 3.3 构造函数和析构函数3.3.1构造函数对象在初始化时,由于具有特定的意义,有时还要分配内存空间,因此,需要有意义的初始值,并完成相应的操作。例如,一张桌子,要有相应的重量、高度、宽度、长度。一个学生,要有姓名、学号,性别、专业等。对象在创建完再进行初始化是不合适的。由于类的数据成员一般都是私有的或受保护的,不允许外部直接访问,因此,不能象其它变量一样进行简单的初始化。解决的办法就是构造函数构造函数的主要功能是创建对象,为对象分配存储空间,并完成对类实例的初始化,对构造函数要注意以下几个问题:(1)构造函数签名必须与类名一致。(2)构造函数不能被继承,但可以重载。(3)如果一个类不包含构造函数,则系统会提供一个默认的构造函数。(4)构造函数在类的实例被创造时被自动调用,不能显式调用(但在子类的构造函数可以调用基类的构造函数),因而也不用声明返回类型。(5)构造函数的访问修饰符一般是public,如果是p riv ate,则表示这个类不能被派生,也不能被实例化,这通常用于只含有静态成员的类中。例:u si n g S y st e m;c l a ss P o i n t(pu b l i c d o u b l e x,y;pu b l i c P o i n t()构造函数(t h i s.x=0;t h i s.y=0;)pu b l i c P o i n t (d o u b l e x,d o u b l e y)构造函数重载t h i s.x=x;t h i s.y=y;)class teststatic void Main()Point a=new Point();Point b=new Point(3,4);实例化类时,自动调用构造函数)(6)可以在构造函数前加s ta tic 关键字形成静态构造函数,但要注意,静态构造函数用实现初始化类(而不是初始化实例或对象)所需的操作。类的静态构造函数在给定程序中至多执行一次。在程序中第一次发生以卜事件时将触发静态构造函数的执行:创建类的实例。引用类的任何静态成员。如果类中包含用Main方法,那么该类的静态构造函数将在调用Main方法之前执行。如果类包含任何在声明时初始化的静态字段,则在执行该类的静态构造函数时,先要按照顺序执行那些初始化。比如:/静态构造函数的例子using System;class Test(static void Main()(A.FO;B.F();)class A(static A()/静态构造函数(Console.WriteLine(执行A的静态构造函数来初始化A);public static void F()Console.WriteLine(调用 A.F()”);c l a ss Bst a t i c B()/静态构造函数C o n so l e.W r i t e L i n e (执行B的静态构造函数来初始化B);pu b l i c st a t i c v o i d F()C o n so l e.W r i t e L i n e (调用 B.F();静态构造函数是C#的一个新特性,在编程过程中用处并不广,它 的:要目的是用于初始化一些静态的变量。因为这个构造函数是属于类的,而不属于任何一个实例,所以这个构造函数只会被执行一次,而且是在创建此类的第一个实例或引用任何静态成员之前,由.N E T自动调用。在使用静态构造函数的时候应该注意几点:1、静态构造函数既没有访问修饰符,也没有参数。因为是.N E T调用的,所 以 像pu b l i c和pr i v a t e等修饰符就没有意义了。2、在创建第一个类实例或任何静态成员被引用时,.NET将自动调用静态构造函数来初始化类。一一也就是说我们无法直接调用静态构造函数,也不可能知道静态构造函数何时会被调用。3、一个类只能有一个静态构造函数。4、无参数的构造函数可以与静态构造函数共存。一尽管参数列表相同,但一个属于类,一个属于实例,所以不会冲突。5、最多只运行一次。6、静态构造函数不可以被继承。7、如果没有写静态构造函数,而类中包含带有初始值设定的静态成员,那么编译器会自动生成默认的静态构造函数。3.3.2 析构函数析构函数用r 销毁类的实例。析构函数是自动调用的,它不能被显式调用。当任何代码都不再可能使用一个实例时,该实例就符合被销毁的条件。此后,它所对应的实例析构函数随时均可能被调用,但是调用时机由公共语言运行时的垃圾回收机制确定,而不是由用户程序确定。其声明形式如下:类名()函数体注意:C#的析构函数不会在对象无效时被立即执行。所以,如果某种资源需要在对象无效时立即被释放,那么释放这种资源的代码就不应该在析构函数中。3.4 关键字this关键字th is 有两种基本的用法,-是用来进行th is 访问,二是在声明构造函数时指定需要先执行的构造函数。3.4.1 th is 访问在类的实例构造函数和实例函数成员中,关键字th is 表示当前的类实例或者对象的引用。th is 不能用在静态构造函数和静态函数成员中,也不能在其他地方使用。当在实例构造函数或方法内使用了与字段名相同的变量名或参数名时,可以使用 this来区别字段和变量或者参数。下面的代码演示了 this的用法。p u b l i c c l a s s D o g(p u b l i c s t r i n g n a m e;p u b l i c i n t a g e;p u b l i c D o g()()p u b l i c D o g (s t r i n g n a m e)/在这个函数内,n a m e 是指传入的参数n a m e(t h i s,n a m e =n a m e;/t h i s.n a m e 表示字段 n a m e)p u b l i c D o g (s t r i n g n a m e,i n t a g e)器在这个函数内,n a m e 是指传入的参数n a m et h i s.n a m e =n a m e;t h i s.a g e 二 a g e;/a g e 是指传入的参数a g e/t h i s,n a m e 表示字段 n a m e/t h i s.a g e 表示字段 a g e实际上,this被定义为一个常量,因此,虽然在类的实例构造函数和实例函数成员中,this可以用于引用该函数成员调用所涉及的实例,但是不能对this本身赋值或者改变this的值。比如,this+,th或之类的操作都是非法的。3.4.2 this用于构造函数声明可以使用如下的形式来声明实例构造函数:访问修饰符【类名】(形式参数表):this(实际参数表)(【语句块】)其中的this表示该类本身所声明的、形式参数表与 实际参数表最匹配的另一个实例构造函数,这个构造函数会在执行正在声明的构造函数之前执行。比如:/关键字t h i s 用于声明构造函数u s i n g S y s t e m;c l a s s A(p u b l i c A(i n t n)(Co n s o l e.W r i t e L i n e (A.A(i n t n)”);p u b l i c A(s t r i n g s,i n t n):t h i s (0)(Co n s o l e.W r i t e L i n e (Z,A.A(s t r i n g s,i n t n)”);)c l a s s T e s t(s t a t i c v o i d M a i n()(A a =n e w A (A Cl a s s”,1);)此例说明,执行构造函数A (str i n g s,i n t n)之前先执行了构造函数A (i n t n).3.5 域(字段)域又称为字段,指类中或实例中的变量。3.5.1静态和实例字段略3.5.2只读字段r eadon l y关键字是可以在字段上使用的修饰符。当字段声明包括r eadon l y修饰符时,该声明引入的字段赋值只能作为声明的一部分发生,或者发生在同一类的构造函数中。对只读字段,只能在下列上下文中进行赋值:(1)当在声明中初始化变量时,例如:p ubl i c r eadon l y i n t y=5;(2)对于实例字段,在包含字段声明的类的实例构造函数中;或者,对于静态字段,在包含字段声明的类的静态构造函数中。只有在这些上下文中时,将 r eadon l y字段传递为out或r ef参数才有效。/cs_r eadon l y_k eywor d.cs/R eadon l y f i el dsusi n g S ystem;p ubl i c cl ass R eadO n l yT est(cl ass M vC l ass(p ubl i c i n t x;p ubl i c r eadon l y i n t y=25;/I n i ti al i ze a r eadon l y f i el dp ubl i c r eadon l y i n t z;p ubl i c M yC l assO(z=24;/I n i ti al i ze a r eadon l y i n stan ce f i el d)p ubl i c M yC l ass(i n t p l,i n t p 2,i n t p 3)xp l ;y=p 2;z=p 3;)p ubl i c stati c voi d M ai n()(M yC l ass p l=n ew M yC l ass(11,21,32);/O KC on sol e.W r i teL i n e(,p l:x=0,y=l,z=,p l.x,p l.y,p l.z);M yC l ass p 2=n ew M yC l ass();p 2.x=5 5;/O Kp 2.y=100;/er r orC on sol e.W r i teL i n e(z/p 2:x=0,y=l,z=2,p 2.x,p 2.y,p 2.z);)注意:如果一个值在整个程序中保持不变,并且在编写程序时就已经知道这个值,那么就应该使用常量。如果这个值在编写程序时不知道,而是程序运行时才能得到,而且一旦得到这个值,值就不会在改变,那么就应该使用只读变量。3.6 方法方法(method)用来计算和实现类的功能,通常在C#中,把函数称为方法。3.6.1定义定义函数的一般格式为:修饰返回值类型函数名(参数)(代码块 Return返回值例:定义一函数求两数的较大值。注意:当没有返回值时,要使用关键字void。3.6.2调用1、在函数调用时,参数与定义时的参数必须匹配。2、若要通过引用传递参数,在定义和调用时加关键字r ef 即可。3.6.3输出参数在调用一个方法时,要进行相应的参数传递。参数有以下几类:(1)值参数(val ue p ar am eter s):即为常量值,即为值传递,不需要修饰符。(2)弓|用参数(r ef er en ce p ar am eter s):即为地址传递,用 r ef 修饰。(3)输出参数(outp ut p ar am eter s):用 out 修饰符。(4)参数数组(p ar am s p ar am eter s):用 p ar am s 修饰符。有时若希望从函数中返回多个值,就要使用输出参数-out关键字。此时只需在定义和调用时使用此关键字即可,但要注意,在调用的模块中对该变量无需进行初始化,若已经初始化,则在调用时其原值会丢失。usi n g S ystem;cl ass m ycl ass(p ubl i c stati c i n t m ax(i n t a,i n t b,out i n t c)(i n t m ax;i f(a b)m ax=a;el sem ax=b;c=a+b;r etur n m ax;)stati c voi d M ai n Oi n t x=10;i n t y=20;i n t z;定义即可,无需初始化。C on sol e.W r i teL i n e(m ax(x,y,out z);C on sol e.W r i teL i n e(z,a=0,b=l,z=2z,,x,y,z);)usi n g S ystem;cl ass T estp ubl i c i n t a;p ubl i c stati c i n t b;p ubl i c T est(i n t m,i n t n)(a=m;b=n;)p ubl i c voi d D M eth Oa=a+5;b=b+5;)p ubl i c stati c voi d S M eth()(/a=a+5;b=b+5;)cl ass E xamp ubl i c stati c voi d M ai n()(T est tl=n ew T est(5,10);T est t2=n ew T est(15,20);tl.D M eth O ;t2.D M eth O ;/tl.S M eth();/t2.S M eth ();T est.S M eth ();/C on sol e.W r i teL i n eC tl.a=0,11.b=”,tl.a,tl.b);C on sol e.W r i teL i n eC tl.a=0,T est.b=l z/,tl.a,T est,b);/C on sol e.W r i teL i n e(z,t2.a=0,t2.b=l ”,t2.a,t2.b);C on sol e.W r i teL i n e(,zt2.a=0,T est,b=1 ,t2.a,T est,b);)分析程序中绿色部分的原因及程序的执行结果。3.6.4参数数组params关键字可以指定在参数数目可变处采用参数的方法参数,即当实参的数目不固定时,可用该关键字修饰形参,以定义一个参数数组。例:usi n g S ystem;cl ass P ar am sT est(stati c voi d P ar am sM eth(r ef i n t sum,p ar am s i n t ar r )i n t i;f or(i=0;i ar r.L en g th;i+)(sum=sum+ar r i ;ar r i =ar r i *ar r i ;)stati c voi d M ai n Oi n t a=l,2,3;i n t i,s=0;P ar am sM eth(r ef s,a);C on sol e.W r i teL i n e(和为0”,s);f or (i=0;i a.L en g th;i+)C on sol e.W r i teL i n e(z,a 0=”,i,a i );P ar am sM eth(r ef s,23,4 5);C on sol e.W r i teL i n e(和为:0”,s);P ar am sM eth (r ef s,1,2,3,4,5,6,7,8,9,10);C on sol e.W r i teL i n e(和为:0 ,s);)练习:分析下面程序的执行结果/cs_p ar am s.csusi n g S ystem;p ubl i c cl ass M yC l ass(p ubl i c stati c voi d U seP ar am s(p ar am s i n t l i st)(f or (i n t i =0;i l i st.L en g th ;i+)C on sol e.W r i te(z z 0”,;C on sol e.W r i teL i n e();)p ubl i c stati c voi d U seP ar am s2(p ar am s obj ect l i st)(f or (i n t i =0;i y)r e t u r n x;e ls er e t u r n y;)pu b lic s t r ing ma x(s t r ing x,s t r ing y)if (s t r ing.C ompa r e (x,y)0)r e t u r n x;e ls er e t u r n y;)s t a t ic v oid Ma inO(C ons ole.W r it e L ine(ne w my c la s s().ma x(10,20);C ons ole.W r it e L ine(ne w my c la s s().ma x(d a b c ,a b c);)3.6.6运算符重载运算符重载主要是给运算符赋予不同的功能,例 如,“十”可以求数值型数据的和,也可以对字符串型数据进行连接等。可以重载的操作符有:一元:+-!+t r u e f a ls e二元:+-*/%&|=!=0 )C ons ole.W r it e L ine(z,0 +1 i,a,b);e ls eC ons ole.W r it e L ine(,z 0 -l iz/,a,-b);c la s s T e s tpu b lic s t a t ic v oid Ma in()(int s n;s t r ing s c;C omple x x=ne w C omple x(1,2);x.D is pC om();C omple x y=ne w C omple x(3,4);y.D is pC om();C omple x z=ne w C omple x(0,0);z=x+y;z.D is pC omO;s n=10+20;s c=a b c+123;C ons ole.W r it e L ine (0 ,,s n,s c);3.6.7外部方法外 部 方 法 主 是 是 为 C#提供了 种访问其它语言(如C+)中定义的函数及W ind ow s A P I 函数的方法。基本过程:(1)引入 System.Runtime.InteropServices 命名空间。(2)引入动态链接库及函数的入口:D I 1I mpor t CZK E R N E L 32.D L L,E nt r y P oint=Mov e F i le W”,S e t L a s t E r r or=t r u e,C ha r S e t=C ha r S e t.U nic od e,E x a c t S pe lling=t r u e,C a llingC onv e nt ion=C a llingC onv e nt ion.S t d C a ll)其中入口点E nt r y P oint 标识函数在动态链接库的入口位置。(3)函数声明所有外部方法都要声明为s t a t ic,并冠以e x t e r 1,表明该方法为外部方法,但不要实现。pu b lic s t a t ic e x t e r n b ool Mov e F ile(S t r ing s r c,S t r ing d s t);注意:可以把这个入口点映射为一个不同的名字,也就是对函数进行重命名。若要实现此功能,则(1)中 E nt r y P oint 可省略。(4)函数调用跟其他函数的调用一样。u s ing S y s t e m;u s ing S y s t e m.R u nt ime.I nt e r opS e r v ic e s;na me s pa c e C ons ole A pplic a t ionlOc la s s P r ogr a m D llI mpor t(K E R N E L 32.D L L,E nt r y P oint =Mov e F ilc W,S e t L a s t E r r or =t r u e,C ha r S e t =C ha r S e t.U nic od e,E x a c t S pe lling=t r u e,C a l1ingC onv e nt ionC a l1ingC onv e nt ion.S t d C a l1)p