《叩开C#之门》系列之四Word格式.docx

上传人:b****2 文档编号:616204 上传时间:2023-04-29 格式:DOCX 页数:12 大小:21.06KB
下载 相关 举报
《叩开C#之门》系列之四Word格式.docx_第1页
第1页 / 共12页
《叩开C#之门》系列之四Word格式.docx_第2页
第2页 / 共12页
《叩开C#之门》系列之四Word格式.docx_第3页
第3页 / 共12页
《叩开C#之门》系列之四Word格式.docx_第4页
第4页 / 共12页
《叩开C#之门》系列之四Word格式.docx_第5页
第5页 / 共12页
《叩开C#之门》系列之四Word格式.docx_第6页
第6页 / 共12页
《叩开C#之门》系列之四Word格式.docx_第7页
第7页 / 共12页
《叩开C#之门》系列之四Word格式.docx_第8页
第8页 / 共12页
《叩开C#之门》系列之四Word格式.docx_第9页
第9页 / 共12页
《叩开C#之门》系列之四Word格式.docx_第10页
第10页 / 共12页
《叩开C#之门》系列之四Word格式.docx_第11页
第11页 / 共12页
《叩开C#之门》系列之四Word格式.docx_第12页
第12页 / 共12页
亲,该文档总共12页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

《叩开C#之门》系列之四Word格式.docx

《《叩开C#之门》系列之四Word格式.docx》由会员分享,可在线阅读,更多相关《《叩开C#之门》系列之四Word格式.docx(12页珍藏版)》请在冰点文库上搜索。

《叩开C#之门》系列之四Word格式.docx

而下面的两行代码则是正确的:

radius=2.5;

类的字段其实也是变量。

如系列三中的类User,就包含有字段m_name,m_password,m_tryCounter。

它们

的类型分别为string,string,int。

字段仍然可以利用public,internal,protected,private来修饰

它。

不过,我建议如非特殊情况,不要将字段修饰为public。

因为,根据”对象封装”的原则,应尽量避

免将一个类型的字段以公有方式提供给外部。

毕竟,对于字段而言,对象对它的控制非常弱,一旦公开在

外,则调用者可以比较容易的对其进行操作,尤其是写操作,从而可能会导致错误。

例如,我们为前面定

义的User类增加一个age(年龄)字段,假如我将其定义为public字段,如下所示:

publicintAge;

那么调用者可能会将Age的值设为负数:

user.Age=-5;

对于字段的定义而言,并不能判断这样一种不合常理的操作,因为我们对字段的写操作的控制无能为力。

大家可以看到,这里所谓的字段值,其实可以对应于前面所讲的对象的属性。

例如姓名,年龄,就是一个

用户的属性。

如果字段不能设置为public,那么调用者又如何访问它们呢?

答案就是使用C#类中的

property(属性)。

所谓“属性”,很大程度可以看作是对“字段”的一种封装,它利用一种被称为“get/set访问器”分别

控制对字段的读写操作,并暴露一个属性值,如Age属性:

privateintm_age;

publicintAge

{

 

get{returnm_age;

}

set

if(value<

0)

{

thrownewArgumentOutOfRangeException(”Agemustbegreaterthanorequalto0″);

}

m_age=value;

上面的代码中,throw语句的作用是抛出一个异常,我们暂时可以不去理会它,而是将注意力放到get和

set访问器上。

首先,我们定义了一个私有字段m_age,然后再定义一个公共属性Age。

在该属性中,get返

回私有字段的值m_age,而在set中,首先会判断value的值,如果小于0,那么这个值是非法的,就将抛出

一个异常,停止往下执行,并告诉你对Age值的设置错误了。

当然,我们也可以为value值设置更严格的要

求,例如不允许value大于150。

至少人的年龄现在没有超过150岁的吧。

也许会有人疑问value究竟是什么?

它其实是C#中提供的关键字,代表的就是你赋给该属性的真正的值,

例如:

user.Age=30;

此时是对Age属性赋值,.Net会执行set访问器,而value值就是30。

然后判断30是否小于0。

显然不符合条

件,不会抛出异常,继续执行,将value值30赋给字段m_age。

为什么要赋给m_age呢?

让我们再看看get访

问器,它其实就是一个读操作,返回的值是什么?

对了,就是字段m_age,如下所示:

//set操作,将字段m_age设置为30;

Console.WriteLine(“User’sAgeis{0}.”,user.Age);

//get操作,将m_age的值取出;

此时就会在控制台下显示:

User’sAgeis30.

此外,对于一些特殊的要求,我们在将字段封装为属性时,可以只设置它的get访问器或者set访问器,这

样这个属性就是只读属性,或者只写属性了。

这样显然更有利于对象的封装。

毕竟对于公共字段而言,我

们最能可以控制它为只读(设置为readonly),却无法设置为只写。

从上可以看到,实际上属性就是对字段进行一次封装。

通过这个封装,使我们对字段m_age的读写都具有

了控制功能,至少现在的Age属性能够控制赋值为负数的情况了。

这就是属性的好处。

在C#2.0中,除了可以对整个属性设置public等访问修饰符外,对内部的get/set访问器同样可以设置访

问修饰符,当然它要受到一定的限制。

由于有些限制和接口、重写有关,我暂时不会介绍,在这里,我仅

介绍访问器和属性的访问修饰符冲突问题。

1、如果整个属性被设置为public,则其访问器没有限制;

2、如果整个属性被设置为protectedinternal,则访问器的访问修饰仅能设置为internal,protected或

者private中的一种;

3、如果整个属性被设置为internal或者protected,那么访问器的访问修饰只能是private。

如下例:

publicClassA

privatestringm_text;

privateintm_count;

publicstringText

get{returnm_text;

protectedset{m_text=value;

internalintCount

privateget{return5;

privateset{m_count=value}

从程序的实质来看,其实属性就是一种特殊的方法,它等同于下面的代码:

publicintGetAge()

returnm_age;

publicvoidSetAge(intage)

m_age=age;

从这个意义上来理解get/set访问器的访问级别修饰,就更容易理解了。

实质上,所谓的访问器的访问级

别修饰,不外乎就是对方法进行访问级别修饰罢了。

当然,C#中提供的属性要比访问字段的get/set方法

更加简便。

一般而言,如要定义方法,应该是和一个对象的行为有关,例如系列三定义的User类中的

SignIn()和SignOut()方法,它们代表的是对象User的行为:

登录和退出。

定义一个类的方法,必须包括五个要素:

方法修饰符,方法名,返回类型,参数,以及方法体,例如Add

方法:

publicintAdd(intx,inty)

returnx+y;

public即为我们的方法修饰符,它代表了该方法能被访问的级别。

当然,修饰的方法的关键字还包括

static,virtual,abstract等,不过这些内容会在以后介绍。

方法名自然是Add了,自然属于方法的名字

返回类型为int,代表该方法会返回一个结果,该结果类型为int类型。

参数有两个,分别为x和y,它们

的类型都是int。

调用者可以通过参数传递值到方法体中,并对它们进行操作。

方法体则是花括号中的内

容。

假设Add方法是定义在类Calculator中,那么该方法的调用为:

Calculatorcal=newCalculator();

intresult=cal.Add(3,5);

通过对Add的调用,并传入3和5的参数,最后得到结果8,并返回。

因此,此时变量result的值就为8。

第一行代码,则是利用new关键字对Calculator类进行实例化,获得一个对象cal。

通过对象cal,才可以

调用Calculator类的公共方法、属性或字段。

为什么要进行实例化呢?

我们定义一个类类型,是为调用者所使用的,否则就失去其意义了。

但我们定义

的这样一个类类型,仅仅是代表了某种格式而已,例如User类说明它是一个class,它拥有了一些字段、

属性和方法。

通过这样的定义,我们在使用这些类型的对象时,.Net能够识别它。

而如果真正要调用这些

类型对象,就必须进行”实例化”,这个操作就会在运行期间,创建一个个对象,并被放在内存空间中供

程序调用。

就好比”人”就是一个类类型,而某一个具体的人,才是被实例化的、真正存在的对象。

要使

得一个类类型被实例化,就需要为该类型提供”构造器”。

构造器是一种特殊的方法,它没有返回类型,

且其方法名和类型名保持一致,如Calculator类的定义以及它的构造器:

publicclassCalculator

publicCalculator()

returnx+y;

Calculator()方法就是一个”构造器”,这个构造器并没有参数,在C#中,也被称为默认的构造器,即使

不定义该构造器,.Net也会为它默认创建。

例如在Calculator类中,我们完全可以删去Calculator()构造

器的定义。

然而,一旦我们定义了有参数的构造器时,则该默认构造器将不存在,如果我们再需要不带参

数创建实例的话,就需要显式创建该构造器了。

例如之前的User类。

如果姓名和密码是该类一个非常重要

的属性,大部分情况下,如果要创建User对象时,都需要这两个属性的值时,我们就可以为User类专门创

建一个构造器:

publicclassUser

publicUser(stringname,stringpassword)

m_name=name;

m_password=password;

}

注意在这个构造器中,接收两个参数name和password,并将其值赋给User类的字段m_name,m_password。

因此,当我们通过如下的方式创建User类的实例时,我们创建的对象就已经具有Name和Password的值了:

UserspecUser=newUser(”brucezhang”,“password”);

然而此时如果利用下面的方式创建User的实例,就会出现错误:

Useruser=newUser();

因为此时User类的默认构造器(即无参的构造器)已经不存在,如要支持上面的实例化方式,就需要在

User类的定义中添加无参构造器。

是否需要为一个类定义有参的构造器,应根据具体的需要而定。

以User类而言,由于该类的Name和

Password属性是一个对象必备的,那么建立这样一个构造器是有必要的。

因为如果不具备这样的构造器,

那么如前构造的specUser就需要用下面三行代码来完成:

UserspecUser=newUser();

specUser.Name=“brucezhang”;

specUser.Password=“password”;

注意,在一个类的定义中,我们可以使用this关键字来代表其类对象本身,通过this,可以访问到这个类

的所有常量、字段、属性和方法,不管它们是public还是private,或者其他访问级别。

虽然这个this指

代的是类对象本身,也就是说它代表的就是实例化所产生的对象,但this的含义也仅仅限于对象的内部,

从对象封装的思想来看,它是被封装了的,在对象外部是无法看到的。

例如下面的定义:

publicclassVistor

publicvoidVisit(Elemente)

Console.WriteLine(”Iwasvisited.”);

publicclassElement

publicvoidAccept(Visitorv)

v.Visit(this);

在Element类中,Accept方法则传入一个Visitor类型的参数值,在该方法中,调用参数v的方法Visit,而

Visit方法传入的是Element类型的值,由于Accept方法本身就属于Element类,因此,我们可以把其自身

传递到Visit方法中,也就是代码中的this。

分析如下的代码段:

Vistorv=newVistor();

Elemente=newElement();

e.Accept(v);

Element的实例e,执行了Accept()方法,该方法传入的参数是Visitor类的实例v。

那么执行Accept方法,

实质就是在其方法内部执行v.Visitor()方法,并通过this关键字将对象e本身传入,所以最后的结果是,

打印如下的字符串:

Iwasvisited。

这这里顺便提一下命名的要求。

所谓命名规范,在作为团队开发的时候,是非常重要的。

以本文为例,如

何定义类名、字段名、属性名和方法名,都是有讲究的。

通常来说,类名、属性名和方法名都要求所有单

词的首字母大写。

如果是字段,那么除非是公共字段,一般而言,应将第一个单词的首字母小写。

不过这

也是变量命名的要求。

由于在一个类中,可能会临时用到一些变量,而不是字段,为了区别一般变量和字

段,C++的程序员喜欢在变量名前加上“_”符号,许多C#程序员也沿用了这个习惯。

不过我更喜欢为这些

字段名前加上“m_”。

命名一定要统一,尤其是在一个团队中,不过类似于这些临时变量,或者非公有变

量,对名字的限制要少一些,毕竟这些变量不会被类的调用者使用。

此外,对于常量而言,最好定义为全

部大写的名字,如前面的定义的常量PI。

C#专门有一套完整的命名规范,有兴趣的可以自己去查阅一下专门的资料。

此外,不同的公司可能还有一

些特定的命名规范,在这里就不再赘述了。

2Comments»

前几天没时间,今天晚上看完了你写的四,终于能够透彻理解属性了.不过,对于this我还是模模糊糊,感觉

没看明白.虽然知道this就是指的是本类的对象,但是,当一个类创建了好几个对象后,

是不是就不能用this了,如果能用,它代表哪个?

再就是this是不是就是代表它所在类的一个通用的对象?

然,为什么一个类没创建对象,仍然可以用this,你举的例子里面就是.

(感觉好像有点像方法里的形参作用一样).在你举的例子中后来创建了一个对象,那this就代表这个对象,

如果创建了2个对象那,那它代表哪个?

Commentby不染丹心—May1,2006@11:

18pm

@不染丹心:

我说了,“this的含义也仅仅限于对象的内部”。

因此,对于实际实例化的对象而言,你不能直接使用

this。

实际上,在对象内部,this就代表对象实例本身。

假设类的方法Foo()中使用了this。

当你创建了

一个实例a,并调用方法Foo,此时this就指代实例a。

如果你同时又创建了实例b,也调用方法Foo,此时

this就指代实例b。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工程科技 > 能源化工

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2