版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
本教程介紹.NET平臺(tái)上主流的編程語言C#,為讀者學(xué)習(xí)ASP.NET技術(shù)打卜基礎(chǔ)。C#
是一門新設(shè)計(jì)的語言,它#吸收了其前輩如C++、Java和Delphi等長處,擁有相當(dāng)豐富的語
肅特性。本章僅介紹使用C#進(jìn)行面向?qū)ο缶幊痰幕A(chǔ)知識(shí),重點(diǎn)在于講清楚面向?qū)ο缶幊?/p>
中的一些重要而基礎(chǔ)的概念。
1面向?qū)ο蠹夹g(shù)概論
面向?qū)ο罄碚摵茉缇捅惶岢鯰,但它真正地滲透到軟件開發(fā)的各個(gè)領(lǐng)域,并且在軟件開
發(fā)實(shí)踐中大規(guī)模應(yīng)用,卻要等到上世紀(jì)九十年代。到目前為止,面向時(shí)象技術(shù)已是軟件開發(fā)
的主流,全面取代了結(jié)構(gòu)化編程技術(shù)曾經(jīng)具有的地位。
面向?qū)ο蠹夹g(shù)結(jié)構(gòu)化編程技術(shù)有著不同的風(fēng)格,但同時(shí)也有著密切的聯(lián)系。從具體編
程角度來看,面向?qū)ο蠹夹g(shù)與結(jié)構(gòu)化編程技術(shù)很難截然分開,兩者的根本差別在廣思維方式。
要r解面向?qū)ο蠹夹g(shù),得從結(jié)構(gòu)化編程技術(shù)入手。
1.1結(jié)構(gòu)化編程引例
結(jié)構(gòu)化編程在上世紀(jì)七十年代興起,由于它具有很多的優(yōu)點(diǎn),出現(xiàn)之后沒幾年就占據(jù)了
軟件開發(fā)的主流,大家熟悉的C語言就是?種典型的結(jié)構(gòu)化編程語言。
結(jié)構(gòu)化編程的雄本方法是“功能分解法”,具體來說,就是將要解決的實(shí)際問題進(jìn)行分
解,把一個(gè)大問題分成若干個(gè)子問題,每個(gè)子問題又可以被分解為更小的問題,直到得到的
子問題可以用一個(gè)函數(shù)來實(shí)現(xiàn)為止。
我們先從一個(gè)簡的的編程任務(wù)開始,逐步體會(huì)結(jié)構(gòu)化編程與面向?qū)ο缶幊痰牟煌L(fēng)格.
請(qǐng)行以卜的這道編程題目:
請(qǐng)編程計(jì)算出1999年5月10日到2006年3月8日期間一共有多少天?
這是?個(gè)簡單的算術(shù)問題,盡管如此,為了作個(gè)鋪舉,我們還是把計(jì)算方法再敘述?下,
以幫助讀擰理清思路.
有以下屆本常識(shí):
?一年有365天,但閏年有366天;
?一年有12個(gè)月,大月31天,小月30天;
?2月最料殊,普通年有28天,閏年有29天。
根據(jù)以上應(yīng)本常識(shí),計(jì)算步驟如下:
(1)計(jì)算從1999到2006期間共有多少個(gè)整年:
2000、2001,2002、2003、2004、2005,共有6個(gè)整年,其中2000和2(X(4年是閏年,因
此,共有6X365+2=2192天.
(2)計(jì)算從1999年5月10日到年底(即12月31日)共有多少天:
5月1()日到12月31日中共有4個(gè)整的大月(7月、8月、10月、12月),3個(gè)整的小月
(6月、9月、11月),共記4X31+3X30=214天。
5月1()日到本月底(31日)還有31-10=21天。
所以,1999年5月10日到年底共有214+21=235天。
(3)計(jì)算從2006年元旦到2006年3月8日期間一共有多少天:
1月有31天,2006年不是閏年,2月有28天,所以,總共有31+28+8=67天。
綜上所述,1999年5月10日到2006年3月8日期間一共有2192+235+67=2494天。
事實(shí)E,上述計(jì)算過程其實(shí)就是一個(gè)計(jì)算機(jī)算法(algorithm),由于步驟很明確,可以
很容易地將這一過程轉(zhuǎn)為程序.
編程之前,先將實(shí)際問題抽象為以卜模型(圖1):
輸入:___產(chǎn)皮________取輸出:
兩個(gè)日期=?/不王仔—7兩個(gè)日期間的天數(shù)
圖1程序的最高層抽象
如圖I所示,我們要完成的工作就是開發(fā)出這樣一個(gè)程序:程序接收兩個(gè)日期值,經(jīng)
過計(jì)算之后,輸出這兩個(gè)H期之間的天數(shù)。
(1)結(jié)構(gòu)化分析過程
為了清晰地表達(dá)出程序需要處理的信息,先定義?個(gè)結(jié)構(gòu)體類型:
〃封裝日期信息
publicstructMyDate
(
publicintYear;〃年
publicintMonth;〃月
publicintDay;//日
結(jié)構(gòu)體類型MyDate其實(shí)是定義了?種數(shù)據(jù)結(jié)構(gòu)(datastmctuie),我們正是在這個(gè)數(shù)
據(jù)結(jié)構(gòu)之上構(gòu)建出整個(gè)程序的。
對(duì)圖1所示的模型進(jìn)行結(jié)構(gòu)化分析的第一步,是將“程序”方框完成的功能轉(zhuǎn)化為由
一個(gè)函數(shù)CalculateDaysOfTwoDateQ實(shí)現(xiàn):
〃計(jì)算兩個(gè)日期中的整天數(shù)
staticintCalculateDaysOfTwoDate(MyDatebeginDate,MyDateendDate)
(
//...
余卜的開發(fā)工作體現(xiàn)為給CalculateDaysOfTwoDateO編寫代碼實(shí)現(xiàn)日期計(jì)算的功能。
在結(jié)構(gòu)化編程中,有這樣一個(gè)重要的公式:
程序=數(shù)據(jù)結(jié)構(gòu)+算法
數(shù)據(jù)結(jié)構(gòu)代表「要處理的信息,而算法則表明要對(duì)這些信息進(jìn)行哪些處理工作。
只要確定了數(shù)據(jù)結(jié)構(gòu)和算法,一個(gè)程序就成形了。因此,
將程序中要處理的數(shù)據(jù)抽象為某種數(shù)據(jù)結(jié)構(gòu)是結(jié)構(gòu)化編程的基礎(chǔ).
在本例中,算法非常簡單,可以直接將人計(jì)算過程中的每?個(gè)步驟轉(zhuǎn)為?個(gè)函數(shù),由此
得到以下兩個(gè)函數(shù):
//計(jì)算兩年之間的整年天數(shù),不足一年的去掉
staticintCalculateDaysOfTwoYear(intbeginYearrintendYear)
(
//??????
)
〃根據(jù)兩個(gè)日期,計(jì)算出這兩個(gè)日期之間的天數(shù),不理會(huì)中間的整年
staticintCalculateDaysOfTwoMonth(MyDatebeginDate,MyDateendDate)
(
//……
第一個(gè)函數(shù)根據(jù)兩個(gè)年份之間的整年數(shù)計(jì)算出天數(shù),第二個(gè)函數(shù)根據(jù)月和日計(jì)算出兩個(gè)
口期之間的大數(shù)(不理會(huì)中間的整年)。
在深入地考慮這兩個(gè)函數(shù)的具體實(shí)現(xiàn)算法時(shí),會(huì)發(fā)現(xiàn)它們都需要判斷一年是否是閏年,
于是,設(shè)計(jì)另?個(gè)函數(shù)IsLeapYear。完成此功能:
〃根據(jù)年數(shù)判斷其是否為閏年
staticboolIsLeapYear(intyear)
(
//……
)
這樣,函數(shù)CalculateDaysOfTwoYear()和CalculateDaysOfTwoMonth()/i:需要的時(shí)候即可
調(diào)用IsLeapYearQ函數(shù)來判斷是否某年為閏年。
至此設(shè)計(jì)工作完成,得到了以下結(jié)果(圖2):
圖2結(jié)構(gòu)化程序設(shè)計(jì)結(jié)果
圖2展示了結(jié)構(gòu)化分析得到的設(shè)計(jì)方案,圖中的箭頭表示函數(shù)調(diào)用關(guān)系。
在整個(gè)結(jié)構(gòu)化分析過程中,我們采用的是先設(shè)iHM最頂層的CalculateDaysOfIWoDate()
函數(shù)的接Fl,再設(shè)計(jì)第二層的兩個(gè)函數(shù)CalculateDaysOfTwoYear()和
CalculateDaysOfTwoMonthO?最后抽象出第三層的函數(shù)IsLeapYearO?
有了設(shè)計(jì)圖,即可動(dòng)手寫代碼?,F(xiàn)在行四個(gè)函數(shù)需要開發(fā),如何確定開發(fā)順序?
很明顯,必須先開發(fā)IsLeapYear。函數(shù),因?yàn)榇撕瘮?shù)被其他函數(shù)調(diào)川,但它不調(diào)用其他
的函數(shù)。
接著可以開發(fā)CalculateDaysOfTwoMonthOfl1CalculateDaysOfTwoYear。兩個(gè)函數(shù),因?yàn)?/p>
CalciilateDaysOfTwoYear()函數(shù)比較簡單,所以先開發(fā)它。
最后開發(fā)CalculateDaysOfTwoDate。函數(shù)。
上述開發(fā)次序的確定可以用兩句話來表達(dá):
(1)蓋樓先打地基:先開發(fā)最底層的函數(shù),因?yàn)椴煌瓿砷_發(fā)這些函數(shù),調(diào)用它們的上
層函數(shù)就無法運(yùn)行。
(2)柿子撿軟的捏:在同一層次的函數(shù)中,先開發(fā)簡單的,再開發(fā)復(fù)雜的。
函數(shù)開發(fā)完成之后,以下代刷調(diào)用最頂層函數(shù)CalculateDaysOfTwoDateO完成計(jì)算兩H
期之間天數(shù)的工作:
MyDatedl,d2;//起始日期和結(jié)束日期
//1999年5月10日
dl.Year=1999;
dl.Month=5;
dl.Day=10;
〃2006年3月8日
d2.Year-2006;
d2.Month=3;
d2.Day=8;
〃計(jì)算結(jié)果
intdays-CalculateDaysOfTwoDate(dl,d2);
現(xiàn)在可以對(duì)結(jié)構(gòu)化編程方法作個(gè)小結(jié)。
?結(jié)構(gòu)化軟件系統(tǒng)的基本編程單位是函數(shù)。
?帔個(gè)系統(tǒng)按功能劃分為若干個(gè)模塊,每個(gè)模塊都由邏輯上.或功能上相關(guān)的若干個(gè)函
數(shù)構(gòu)成,各模塊在功能上相時(shí)獨(dú)立.
?公用的函數(shù)存放在公用模塊中,各模塊間可以相”調(diào)用,擁有調(diào)用關(guān)系的模塊形成
一個(gè)樹型結(jié)構(gòu),這種調(diào)用關(guān)系應(yīng)盡可能做到是單向的。
結(jié)構(gòu)化軟件系統(tǒng)的架構(gòu)如圖3所示:
圖3結(jié)構(gòu)化軟件的架構(gòu)
結(jié)構(gòu)化編程的開發(fā)過程可以分為以下三個(gè)階段:
(1)分析階段:在編程之前,需要仔細(xì)分析要解決的問題,確定好數(shù)據(jù)結(jié)構(gòu)與算法.
(2)設(shè)計(jì)階段:結(jié)構(gòu)化編程的基本單元是函數(shù),每個(gè)函數(shù)都完成整個(gè)程序的?個(gè)功能,
整個(gè)設(shè)計(jì)過程就是函數(shù)接口的設(shè)計(jì)過程,這是?個(gè)“自頂向下,逐步求精”的過程,將一個(gè)
大函數(shù)不斷分解為多個(gè)小函數(shù),比至可以很容易川某種程序設(shè)計(jì)語音實(shí)現(xiàn)時(shí)為止。
(3)編碼階段:在開發(fā)時(shí),根據(jù)在設(shè)計(jì)階段得到的函數(shù)調(diào)用圖,先開發(fā)最底層的函數(shù),
再開發(fā)匕層函數(shù)。這是一個(gè)“自底向上,逐層蓋樓”的方法。
結(jié)構(gòu)化編程中“自頂向下,逐步求精”的“功能分解法”,是一種重要的軟件開發(fā)方法,
其本質(zhì)是一種''分而治之”的思維方式,在面向?qū)ο蟮某绦蛑幸灿袕V泛的應(yīng)用。掌握這種分
析方法,對(duì)軟件工程師而言是非常重要的。
(2)面向?qū)ο蠓治鲞^程
有了結(jié)構(gòu)化分析的基礎(chǔ),可以很容易的將原先結(jié)構(gòu)化的程序轉(zhuǎn)為面向?qū)ο蟮某绦颉?/p>
創(chuàng)建?個(gè)CalculateDate類,作為上面結(jié)構(gòu)化分析得到的四個(gè)函數(shù)的“新家”,如圖4所
Class
-字段
nonlhs:int[]
-方法
VCalculaiteDaysOfTwoDate()int
券CalculateDaysOfT^olionthO:
CalculateDaysOfTwoYear()int
,4,VTsLeapYear()bool
圖4將函數(shù)移到類中
由「?外界只需要調(diào)用CalculateDaysOfTwoDateO?個(gè)函數(shù),所以將此函數(shù)設(shè)置為公有
(public),而其他:個(gè)函數(shù)則成為類的私行(private)成員,外界不可訪問.
以下為調(diào)用此類完成計(jì)算兩個(gè)口期間天數(shù)的代碼示例:
MyDatedl,d2;〃起始日期和結(jié)束日期
〃1999年5月10日
dl.Year=1999;
dl.Month=5;
dl.Day=10;
〃2006年3月8日
d2.Year=2006;
d2.Month=3;
d2.Day=8;
stringstr="{0}年{1}月{2}日到{3}年(4}月{5}日共有天數(shù):
str=String.Format(strrdl.Year,dl.Month,dl.Day,
d2.Year,d2.Month,d2.Day);
palculateDateobj=newCalculateDate();|〃創(chuàng)建類Ca1culateDate對(duì)象obj
//調(diào)用對(duì)象obj的CalculateDaysOfTwoDate方法計(jì)算
|intdays=obj.CalculateDaysOfTwoDate(dl,d2);]
Console.WriteLine(3tr+days);
對(duì)比前面結(jié)構(gòu)化的程序,不難發(fā)現(xiàn)面向?qū)ο蟮某绦蚓哂幸圆穾讉€(gè)特點(diǎn):
(1)所有的函數(shù)都放入到?個(gè)類中,成為某個(gè)類的成員,類是編程的基本單元。
(2)外界不能直接調(diào)用類的成員函數(shù),必須先創(chuàng)建一個(gè)對(duì)象,再通過對(duì)象來調(diào)用這些
函數(shù).
(3)只有聲明為public的函數(shù)以被外界調(diào)用(本例中為CalculateDaysOfTwoDateO
函數(shù)),其余聲明為private的函數(shù)是私有的,外界無法訪問。
從這個(gè)實(shí)例可以看出,面向?qū)ο蟪绦蚺c結(jié)構(gòu)化程序有著很不一樣的風(fēng)格,但看不出來面
向時(shí)象有何優(yōu)越之處,
的確,對(duì)于這個(gè)小實(shí)例而M,面向?qū)ο蟪绦蚺c結(jié)構(gòu)化程序相比沒有明顯的優(yōu)越性,而且
顯得更麻煩,但如果是大規(guī)模的軟件系統(tǒng),則面向?qū)ο蟪绦蚓陀兄Y(jié)構(gòu)化程序不可比擬的優(yōu)
勢,簡單地說:
對(duì)于大規(guī)模的系統(tǒng),采用面向?qū)ο蠹夹g(shù)開發(fā)可以達(dá)到較高的開發(fā)效率與較低的維護(hù)成
本,系統(tǒng)的可擴(kuò)展性也更好。
食本節(jié)的小例子而言,其實(shí).NETFramework本身就提供了兩個(gè)類DateTiine和TiineSpaii
可完成同樣的功能:
DateTimeddl,dd2;
ddl=newDateTime(2006,3,8);
dd2=newDateTime(1999,5,10);
//兩個(gè)日期對(duì)象相減,得到一個(gè)TimeSpan對(duì)象,Days是這一TimeSpan對(duì)象的屬性
intddays"(ddl-dd2).Days;
Console.WriteLine(ddays)"/結(jié)果:
對(duì)比一下,顯然使用.NETFramework提供的現(xiàn)成類比我們手工編寫代碼完成同樣的工
作開發(fā)效率要高得多。.NETFramework中所提供的現(xiàn)成代碼都是以面向?qū)ο蟮男问椒庋b的。
實(shí)踐證明,當(dāng)羔要大規(guī)模地復(fù)用代碼以提高軟件生產(chǎn)率時(shí),面向?qū)ο蟊冉Y(jié)構(gòu)化技術(shù)更有效。
1.2面向?qū)ο蟮暮诵母拍?/p>
從理論上說,面向?qū)ο蠹夹g(shù)擁有四大基本特性。
(1)封裝
這是?種隱藏信息的特性。食本節(jié)引例來說,類CalculateDate將數(shù)據(jù)結(jié)構(gòu)與算法隱藏
在類的內(nèi)部,外界使用者無需知道具體技術(shù)實(shí)現(xiàn)細(xì)節(jié)即可使用此類.封裝這?特性不僅大大
提高了代碼的易川性,而旦還使得類的開發(fā)者可以方便地更換新的算法,這種變化不會(huì)影響
使用類的外部代碼??梢杂靡圆饭秸故绢惖姆庋b特性:
封裝的類=數(shù)據(jù)+對(duì)此數(shù)據(jù)所進(jìn)行的操作(即算法)
通俗地說,封裝就是:包起外界不必需要知道的東西,只向外界展露可供展示的東西.
在面向?qū)ο罄碚撝校庋b這個(gè)概念擁有更為寬廣的含義。小到一個(gè)簡單的數(shù)據(jù)結(jié)構(gòu),大
到?個(gè)完整的軟件子系統(tǒng),靜態(tài)的如某軟件系統(tǒng)要收集數(shù)據(jù)信息項(xiàng),動(dòng)態(tài)的如某個(gè)工作處理
流程,都可以封裝到一個(gè)類中。
具備這種“封裝”的意識(shí),是掌握面向?qū)ο蠓治雠c設(shè)計(jì)技巧的關(guān)鍵。
(2)抽象
講到抽象,不得不涉及到現(xiàn)代科學(xué)技術(shù)的基礎(chǔ)數(shù)學(xué)。
數(shù)學(xué)是?門抽象的科學(xué),面對(duì)著紛繁復(fù)雜的世間萬物,數(shù)學(xué)不理會(huì)各種事物的獨(dú)特特性,
而只抽取它們在數(shù)量上的特性,深刻揭示了“世間萬物”在數(shù)量I:表現(xiàn)出的共同規(guī)律,抽象
正是數(shù)學(xué)的本質(zhì)特征。
數(shù)學(xué)的?個(gè)分支一離散數(shù)學(xué)是計(jì)算機(jī)科學(xué)的根基之因此,計(jì)算機(jī)科學(xué)從誕生之口
起,就與數(shù)學(xué)有著密不可分的聯(lián)系,抽象思維也是計(jì)算機(jī)科學(xué)的主要思維方法之
在使用面向?qū)ο蟮姆椒ㄔO(shè)計(jì)一個(gè)軟件系統(tǒng)時(shí),首先就要區(qū)分出現(xiàn)實(shí)世界中的事物所屬的
類型,分析它們擁有哪些性質(zhì)與功能,再將它們抽象為在計(jì)算機(jī)虛擬世界中才有意義的實(shí)體
-類,在程序運(yùn)行時(shí),由類創(chuàng)建出對(duì)象,用對(duì)象之間的相互合作關(guān)系來模擬真實(shí)世界中事
物的相互關(guān)聯(lián)。
在從真實(shí)世界到計(jì)算機(jī)虛擬世界的轉(zhuǎn)換過程中,抽象起了關(guān)鍵的作用。
(3)繼承
真實(shí)世界中,事物之間有著一種派生關(guān)系,比如“食品”這一大類中包括“水果”這
一子類,而“蘋果”又包含在“水果”這一子類中。用圖形表示如圖5:
食品
圖5現(xiàn)實(shí)世界中的事物派生關(guān)系
在計(jì)算機(jī)世界中,以面向?qū)ο蟮挠^點(diǎn)不僅將上述事物抽象為類,而且將事物之間的派生
關(guān)系也一并模擬出來,這種關(guān)系稱為“繼承”(圖6):
圖6用“繼承”模擬現(xiàn)實(shí)中的“派生”關(guān)系
在面向?qū)ο筌浖到y(tǒng)中,繼承除了模擬現(xiàn)實(shí)世界中事物關(guān)系這?作用,還是?個(gè)“重用
己有代碼而又不破壞已有代碼”的方法。舉例來說:
現(xiàn)在要開發(fā)一個(gè)B項(xiàng)目,架構(gòu)設(shè)計(jì)師發(fā)現(xiàn)以前完成的A項(xiàng)目中有部分類完全可以在B
項(xiàng)目中重用,但需要增強(qiáng)這些類的功能以便適用于B項(xiàng)目.如果從A項(xiàng)目中直接抽取這些
類的源代碼并加以修改,雖然可以滿足B項(xiàng)目的需要,但現(xiàn)在卻需要維護(hù)兩官功能類似的
類代碼,加大了管理的成本。在這種情況上選擇從A項(xiàng)目的類中用繼承的方法派生出新
類用在B項(xiàng)目中是一個(gè)可選的方案,既滿足J'新項(xiàng)目的需要,又避免「大鼠的弱發(fā)代碼與
雙倍的代碼維護(hù)成本.
(4)多態(tài)
在現(xiàn)實(shí)生活中,我們常說:蘋果是一種水果(Appleisakindof小山).草果與水果這兩
個(gè)概念之間其實(shí)是種特性。共性的關(guān)系,簡稱為IS_A關(guān)系,其特點(diǎn)為:水果擁行的特性,
蘋果一定有。
在前面的小節(jié)中我們用繼承模擬iIS_A關(guān)系,“水果(Fruit)”是基類,“蘋果(Apple)"
是子類,IS_A關(guān)系可以用另?種方式來建基類擁有的特性,子類一定有因此,可
以把了?類看成是?種“特殊”的基類。
舉個(gè)例子:“給張三一個(gè)蘋果”和“給張三一串香蕉”,雖然是兩件不同的事,卻可以統(tǒng)
一說成“給張三一個(gè)水果
用“給張三一個(gè)水果”來指代“給張三一個(gè)蘋果”和“給張三一串香蕉”,雖然在語義
上比較“模糊”,但其適用性更廣了,除了“蘋果”和“香蕉”,以后還可以是“梨子二“西
瓜”、“葡簡”…….都可以用“給張三一個(gè)水果”來代表。
這種用?個(gè)比較抽象的事物來取代具體的事物的表達(dá)方法,在面向時(shí)象軟件中用“多態(tài)”
這一特件來模擬。
在編程時(shí)應(yīng)用多態(tài)的方法,可以用一句話來表示:
用抽象的類編程
即在代碼中本應(yīng)使用某?具體子類的地方使用較為抽象的基類對(duì)象,這種方法所帶來的
好處是多態(tài)的代碼具有“變色龍”的特性,即在不同的條件下,同樣代碼可以完成不同的功
能。
適當(dāng)?shù)卦陂_發(fā)中應(yīng)用多態(tài)特性,可以開發(fā)出可擴(kuò)充性很強(qiáng)的系統(tǒng)。
(5)小結(jié)
面向?qū)ο蟮乃拇筇匦圆皇潜舜霜?dú)立的,“抽象”和“封裝”更多地體現(xiàn)為?種思維方法,
主要體現(xiàn)在面向?qū)ο笙到y(tǒng)的總體分析和設(shè)計(jì)中,“繼承”和“多態(tài)”則多應(yīng)用于具體子系統(tǒng)
和軟件模塊的設(shè)計(jì)與編碼過程中,而且“繼承”是“多態(tài)”的基礎(chǔ)。
1.3面向?qū)ο蠹夹g(shù)與Web開發(fā)的關(guān)系
在早期靜態(tài)網(wǎng)頁的時(shí)代,網(wǎng)頁主要是由HTML代碼表達(dá)的,Web服務(wù)器完成的工作只
是應(yīng)瀏覽器的請(qǐng)求傳送網(wǎng)頁,職責(zé)單一,除非需要開發(fā)Web服務(wù)器本身,開發(fā)以靜態(tài)網(wǎng)頁
為主體的網(wǎng)站與面向?qū)ο蠹夹g(shù)并沒有什么直接關(guān)系。
在早期的動(dòng)態(tài)網(wǎng)頁技術(shù)(如ASP)出現(xiàn)之后,Web服務(wù)器職責(zé)開始變得復(fù)雜起來,它
不僅僅要完成原先的傳送網(wǎng)頁的工作,還需要完成在傳送網(wǎng)頁之前動(dòng)態(tài)生成網(wǎng)頁的工作。這
時(shí),動(dòng)態(tài)網(wǎng)頁多采用腳本語言比如VBScript/JScript等配合HTML來開發(fā)。
在早期的動(dòng)態(tài)網(wǎng)頁技術(shù)(如ASP)出現(xiàn)之后,Web服務(wù)器職責(zé)開始變得復(fù)雜起來,它
不僅僅要完成原先的傳送網(wǎng)頁的工作,還需要完成在傳送網(wǎng)頁之前動(dòng)態(tài)生成網(wǎng)頁的工作.這
時(shí),動(dòng)態(tài)網(wǎng)頁多采用腳本語言比如'BScript/JScript等配合HTML來開發(fā)。
腳本語言與標(biāo)準(zhǔn)的面向?qū)ο笳Z言相比,一般在語法上有所簡化,在功能上也不如標(biāo)準(zhǔn)的
面向?qū)ο笳Z言強(qiáng)大,并且不支持面向?qū)ο蟮乃?特性,同時(shí)往往也缺乏高效率的開發(fā)工具支
持。
Java平臺(tái)的動(dòng)態(tài)網(wǎng)頁技術(shù)JSP應(yīng)用Seiverlet技術(shù)突破J’網(wǎng)頁開發(fā)不能使用面向?qū)ο笳Z
言與工具的限制,網(wǎng)頁是由在Web服務(wù)器運(yùn)行的Serverlet動(dòng)態(tài)生成的,而Serverlet本身則
使用全面向時(shí)象的Java語言開發(fā)。
在JSP出現(xiàn)并得到廣泛應(yīng)用不久之后,微軟公司于2002年推出了ASP技術(shù)的替代技術(shù)
一ASP.NET,在面向而象的道路上走得更遠(yuǎn)。
ASP.NET將網(wǎng)頁本身看成是一個(gè)類,當(dāng)瀏覽器向Web服務(wù)器請(qǐng)求這個(gè)網(wǎng)頁時(shí),Web服
務(wù)器動(dòng)態(tài)創(chuàng)建這個(gè)類的一個(gè)時(shí)象,然后調(diào)用它的特定方法生成HTML代碼,再將生成的這
些HTML代碼發(fā)回給瀏覽器,
在開發(fā)ASP.NET網(wǎng)頁時(shí),開發(fā)者可以使用C#/VB.NET等面向?qū)ο蟮恼Z言,并以與桌面
程序一致的“所見即所得”與“小件驅(qū)動(dòng)”開發(fā)方式編程。對(duì)比老的ASP技術(shù),ASP.NET
技術(shù)的這些新特點(diǎn),充分說明J'微軟Web開發(fā)技術(shù)已全面步入面向時(shí)象的時(shí)代。
由于ASP.NET技術(shù)是全面向?qū)ο蟮?,因此,要想掌握這一技術(shù),必須具備有扎實(shí)的面
向?qū)ο罄碚摶A(chǔ)
2類與對(duì)象
從本節(jié)開始,介紹C#面向?qū)ο缶幊痰幕緝?nèi)容。
與使用C語言等結(jié)構(gòu)化編程語言不一樣,使用C#編程,所有的程序代碼幾乎都放在類
中,不存在獨(dú)立于類之外的函數(shù)。因此,類是面向?qū)ο缶幊痰幕締卧?/p>
在絕大多數(shù)面向?qū)ο笳Z言中,一個(gè)類都可以包含兩種成員:字段(Field)與方法
(Method)?字段與方法這兩個(gè)概念是面向?qū)ο罄碚摰男g(shù)語,是通用于各種面向?qū)ο笳Z言的。
而在各種的具體面向?qū)ο笳Z言(比如C#)中,可以簡單地這樣理解:
字段即變?,方法即函數(shù).
類的字段一般代表類中被處理的數(shù)據(jù),類的方法大多代表時(shí)這些數(shù)據(jù)的處理過程或用于
實(shí)現(xiàn)某種特定的功能,方法中的代碼往往需要訪問字段保存的數(shù)據(jù).
在C#中,定義若干個(gè)變量:.寫若干個(gè)函數(shù).將這些代碼按以下格式匯集起來,再起個(gè)
有意義的名字,就完成「一個(gè)類的定義:
(publicIprivate]class類名
(
(publicIprivate)數(shù)據(jù)類型變量名;
[publicIprivate]數(shù)據(jù)類型函數(shù)名(參數(shù)列表)
在上述類的定義中,方括號(hào)代表這部分可選,而豎線則代表多選一。聲明為public的變
試和函數(shù)可以被外界直接訪問,與此對(duì)應(yīng),private的變址與函數(shù),則為類的私行成員,只能
由類自己使用。
卜面簡要介紹組成類的基本成員。
2.1類的字段
字段(Field)代表了類中的數(shù)據(jù),在類的所有方法之外定義一個(gè)變量即定義了一個(gè)字
段。在變量之前可以加上public、private和protected表示字段的訪問權(quán)限。以下代碼展示了
在類Student中定義的兩個(gè)公有字段Age和SN.外界可以通過類Student創(chuàng)建的對(duì)象來讀取
或設(shè)置這兩個(gè)字段的值。
可以在定義字段的同時(shí)給予一個(gè)初始值,如下所示:
classStudent
(
publicintage=18;〃年齡
publicstringSN="1220040110M;//學(xué)號(hào)
)
2.2類的方法
(1)函數(shù)的概念
在程序開發(fā)過程中,經(jīng)常發(fā)現(xiàn)多處需要實(shí)現(xiàn)或調(diào)用某一個(gè)公用功能(比如選擇一個(gè)文
件),這些功能的實(shí)現(xiàn)都需要書寫若干行代碼。如果在調(diào)用此功能的地方重復(fù)書寫這些功能
代碼,將會(huì)使整個(gè)程序中代碼大量重宮,會(huì)增大開發(fā)工作量,增加代碼維護(hù)的難摩。
為了解決代碼毛史的問題,絕大多數(shù)程序設(shè)計(jì)語才都將完成某?公用功能的多個(gè)語句組
合在?起,起一個(gè)名字用于代衣這些語句的全體,這樣的代碼塊被稱為“函數(shù)(function),
引入“函數(shù)”概念之后,程序中凡需要調(diào)用此公用功能的地方都可以只寫出函數(shù)名,此名字
就代表了函數(shù)中所包含的所有代碼,這樣一來,就不再需要在多個(gè)地方,K復(fù)書寫這些功能代
碼。
函數(shù)的出現(xiàn),標(biāo)志著軟件開發(fā)進(jìn)入了結(jié)構(gòu)化編程的時(shí)代。調(diào)用和編寫各種函數(shù)是程序
員在結(jié)構(gòu)化編程時(shí)的主要工作之一。
C#中一個(gè)函數(shù)的語法格式如下所示:
返回值類型方法名(參數(shù)列表)
(
語句1;
語句2:
//-
return表達(dá)式;
下面是一個(gè)典型的C#函數(shù)示例:
intAdd(intx,inty)
(
returnx+y;
)
函數(shù)需要向外界返回一個(gè)值,由return語句實(shí)現(xiàn)。
如未?‘「陰效女們返四1R攻小天心只返凹阻,則的只咫凹出4:乂為void
voidf()〃不返回任何值的函數(shù)
(
語句1:
語句2:
//-
return;〃在return后寫一個(gè)空語句
(2)方法的定義與使用
放在?個(gè)類中的函數(shù)(通常附加?個(gè)存取權(quán)限修飾符如public和private)稱為“方法
(method)”。
訪問?個(gè)方法的最基本方式是通過類創(chuàng)建的對(duì)象。例如以卜代碼在類MathOpt中定義
了一個(gè)Add()方法:
publicclassMathOpt
publicintAdd(intx,inty)
returnx+y;
)
上述兩個(gè)函數(shù)有以卜獨(dú)特之處:
(1)函數(shù)名相同,均為Add:
(2)參數(shù)類型不同,一個(gè)為int,另一個(gè)為double。
這兩個(gè)同名的函數(shù)彼此構(gòu)成了“重載(Overload)"關(guān)系.
力我函數(shù)的調(diào)用代碼:
MathOptmathobj=null;〃定義MathOpt對(duì)象變量
mathobj=newMathOpt();〃創(chuàng)建對(duì)象
|int工Resuf¥=mathobj.Add(10。,200)7]//調(diào)用類的整數(shù)相加方法
[doubleFResult=mathobj.Add(5.5,9.汀7]//調(diào)用類的浮點(diǎn)數(shù)相加方法
Console.WriteLine('*100+200="+IResult);〃輸出結(jié)果
Console.WriteLine(n5.5+9.2=H+FResult);〃輸出結(jié)果
請(qǐng)注意標(biāo)為粗體的兩個(gè)方法調(diào)用語句。傳給方法實(shí)參為浮點(diǎn)數(shù)時(shí),將調(diào)用參數(shù)類型為
double的Add(double,double)方法,傳給方法的實(shí)參為整數(shù)時(shí),調(diào)用參數(shù)類型為int的
Add(int.iut)方法。
函數(shù)而載是面向?qū)ο笳Z言對(duì)結(jié)構(gòu)化語言特性的幣:要擴(kuò)充,住面向?qū)ο蟮木幊讨袘?yīng)用極
廣。
兩個(gè)構(gòu)成重載關(guān)系的函數(shù)必須滿足以下條件:
(1)函數(shù)名相同。
(2)參數(shù)類型不同,或參數(shù)個(gè)數(shù)不同。
需要注意的是,函數(shù)返回值類型的不同不是函數(shù)隸載的判斷條件o
比如,函數(shù)
publiclongAdd(intx,inty){...}
就不與函數(shù)
publicintAdd(intx,inty){...}
namespaceConsoleApplication1
(
classProgram
(
intadd(inta,intb)
(
returna+b;
)
floatadd(inta,intb)
(
returna+b;
}
staticvoidMain(string[]args)
(
Programprogram=newProgram();
program.add(l,2);
)
}
)
,三A3
CW,M??,皿《???,?ST\rr???rk\T)5VC?r?>(Zb*ra?f>t/w??mIMl.t!0?/?rrMT?partyrcept/??-?4/<hfii>?DKHV'TUCE/r?far??e?*C\Fr?fr?Fil??(tM)\Raf?r?ae?*>taaMi>?M>rT?>?tttFrHM*art\vlX\$)nta*C?r?4X1,
,wt.uvx.wUM..t?.4Kr?<xxit)m在csoiii盒F“cz“Fh”t;ah.p?■efck7-t?c*)-U4-WIliWWMXSWS
>\IIUr4M』\T?TY",";」y$Ur>J3?《>?】;",;g\C8“1?2t>】iet;MArr?crs?(336.11)(IfiXtQB)
*3ftiK-Jt?l-ot?A
2JKK0)o+?Mt]卞?Mlo十?Rd0十
9O9ftIMRtChi
構(gòu)成重載關(guān)系,因?yàn)檫@兩個(gè)函數(shù)的實(shí)參類型和數(shù)目都相同,僅函數(shù)返回值類型不同。
另外要注意C#是區(qū)分大小寫的語言,因此,如果?個(gè)類中有以下兩個(gè)函數(shù):
publiclongadd(intx,inty){........)
publicintAdd(intxrinty){.........}
則可以通過編譯并且程序可以運(yùn)行,但這并不是說這兩個(gè)函數(shù)構(gòu)成了重載關(guān)系,事實(shí)上,
C#認(rèn)為這是兩個(gè)完全不同的函數(shù),彼此之間一點(diǎn)關(guān)系也沒有!
2.3類的靜態(tài)成員
類中的函數(shù),如果在聲明時(shí)沒有加“static”關(guān)鍵字,則稱之為類的“實(shí)例方法(instance
method),*<,加/static關(guān)鍵字的方法稱為“靜態(tài)方法(staticmethod)".
類似地,加「static美鍵字的字段稱為.?靜態(tài)字段(staticfield)".
(1)訪問類的靜態(tài)成員的基本方法
.NETFrajuework提供了大量的靜態(tài)方法供開發(fā)人員使用,最典型的是數(shù)學(xué)庫函數(shù),.NET
Framework將常用的數(shù)學(xué)函數(shù)放到「類Math中,例如以下代碼計(jì)算2的3次方:
doubleret=Math.Pow(2,3);
對(duì)比前面介紹過的類實(shí)例方法的調(diào)用方式,可以發(fā)現(xiàn)靜態(tài)方法在使用時(shí)不需要?jiǎng)?chuàng)建對(duì)
象,而是按以下格式宜接調(diào)用:
類名.靜態(tài)方法名(參數(shù)列表)
類的實(shí)例方法可以直接訪問類的公布靜態(tài)字段,比如數(shù)學(xué)常數(shù)笊就是Math類的公有靜
態(tài)字段,可以被用來計(jì)算圓周長:
〃計(jì)算圓周長
doubleGetPerimeterOfCircle(Doubleradius)
(
return2*Math.PI?radius;
(2)類靜態(tài)成員的特性
類的價(jià)態(tài)成員有一個(gè)特殊的性質(zhì).先來看一個(gè)例子來說明這一點(diǎn)。
給類StaticMeuibers增加?個(gè)普通的實(shí)例方法increaseValueO和實(shí)例字段dynamicVar(參
見示例項(xiàng)目UseStaticMembers):
classStaticMembers
(
publicstaticintstaticVar=O;〃靜態(tài)字段
publicintdynamicVar=O;
publicvoidincreasevalue()
(
staticVar++;
dyneunicVar++;
在increaseValue()7/111,對(duì)■類的靜態(tài)字段staticVar和實(shí)例字段dyuamicV'ar都進(jìn)行了自
增操作。
以下是測試代碼:
staticvoidMain(string[]args)
(
StaticMembersobj=null;
〃創(chuàng)建100個(gè)對(duì)象
for(inti=0;i<100;i++)
(
obj=newStaticMembers();
obj,increasevalue();
)
〃查看靜態(tài)字段與普通字段的值
Console.WriteLine(MdynamicVar=M+obj.dynamicVar);
Console.WriteLine(MstaticVar=n+StaticMembers.staticVar);
〃程序暫停,敲任意鍵繼續(xù)
Console,ReadKey();
)
程序的運(yùn)行結(jié)果:
dynamicVar=l
staticVar=100
因?yàn)轭惖撵o態(tài)成員擁有以下特性:
類的靜態(tài)成員是供類的所有對(duì)象所共享的。
在本節(jié)示例中創(chuàng)建f100個(gè)對(duì)象,每個(gè)耐象擁力個(gè)dyanmicVar字段,,共'行100個(gè)
dyaiunicVar字段,這些字段是獨(dú)立的,“互不干涉內(nèi)政"。而staticVar字段僅有?個(gè),為所
有對(duì)象所共享。因此,任何一個(gè)對(duì)象對(duì)staticVar字段的修改,都會(huì)被其他對(duì)象所感知(圖7):
100創(chuàng)建了I00個(gè)對(duì)扶享一個(gè)
staticVar字段
圖7靜態(tài)字段與實(shí)例字段
(3)類實(shí)例成員與靜態(tài)成員的訪問規(guī)則
在面向?qū)ο蟮某绦蛑校瑢?duì)類的實(shí)例和靜態(tài)成員,有以下訪問規(guī)則:
?位于同一類中的實(shí)例方法可直接相互調(diào)用.
?類的字段(包括實(shí)例字段和靜態(tài)字段)可以被同一類中的所有實(shí)例方法直接訪問.
?類中的靜態(tài)方法只能直接訪問類嶺態(tài)字段.
上述規(guī)則中,需要特別注意在靜態(tài)方法中直接調(diào)川類的實(shí)例方法是非法的。例如以下代
碼將無法通過編譯。
classStaticMembers
(
publicstaticintstaticVar=O;〃靜態(tài)字段
publicstaticvoidstaticFunc()//靜態(tài)方法
(
increasevalue();〃靜態(tài)方法中不能調(diào)用實(shí)例方法X
dynamicVar++;//靜態(tài)方法中不能訪問實(shí)例字段X
staticVar++;〃靜態(tài)方法可以訪問靜態(tài)字段正確!
)
publicintdynamicVar^O;
publicvoidincreasevalue()
(
staticVar++;
dynamicvar++;
價(jià)態(tài)方法中只允許訪問靜態(tài)數(shù)據(jù).那么.如何在靜態(tài)方法中訪問實(shí)例數(shù)據(jù)?
很簡單,可以在靜態(tài)方法中創(chuàng)建對(duì)象,通過對(duì)象來訪問即可。將靜態(tài)方法staticFiincO
修改如下即可通過編譯:
靜態(tài)方法中只允許訪問靜態(tài)數(shù)據(jù).那么.如何在靜態(tài)方法中訪問實(shí)例數(shù)據(jù)?
很簡單,可以在靜態(tài)方法中創(chuàng)建對(duì)■象,通過對(duì)象來訪問即可。將靜態(tài)方法staticFuncO
修改如下即可通過編譯:
publicstaticvoidstaticFunc()〃靜態(tài)方法
〃在靜態(tài)方法中通過對(duì)象訪問類的實(shí)例成員
|StaticMembersobj=newStaticMembers(方]
obj.increasevalue();//調(diào)用實(shí)例方法,OK!
obj.dynamicVar++;〃訪問實(shí)例字段,OK!
2.4類的屬性
屬性是一種特殊的“字段”。
先來看一個(gè)用于表示學(xué)生信息的類Student:
classStudent
publicStringName;〃姓名
publicDateTimeBirthday;〃生日
publicintAge;〃年齡
Student類中使用公有字段來表達(dá)學(xué)生信息,這種方式無法保證數(shù)據(jù)的有效性。比如外
界完全可以這樣使用Student類:
Studentstu=newStudent();
stu.Name=〃非法數(shù)據(jù),名字怎能為空?
stu.Birthday=newDateTime(3000r1,3);〃公元3000年出生,他來自未來世界?
stu.Age=-1;〃年齡必須大于0!
在設(shè)計(jì)類時(shí)使用屬性(Property)可以保證只有合法的數(shù)據(jù)可以傳給對(duì)象。
以Name這個(gè)字段為例,它要求不能為空。
首先,定義一個(gè)私有的一Name字段:
privateString_Name="姓名默認(rèn)值,
接著,即可定義一個(gè)Name屬性:
publicstringName
(
get〃讀
(
return_Name;
)
set//寫,使用幽含變量value
(
if(value.Length==0)
thrownewException("名字不能為空”);
_Name=value;
Name屬性由兩個(gè)特殊的讀訪問器(get)和寫訪問器(set)組成。
當(dāng)讀取Name屬性時(shí),讀訪問器被調(diào)用,僅簡雅地向外界返回私有字段一Name的值.
當(dāng)設(shè)置Name屬性時(shí),寫訪問器被調(diào)用,先檢查外界傳入的值是不是空,,再將傳入的
值保存于私有字段中。
經(jīng)過這樣的設(shè)計(jì),以下的代碼在運(yùn)行時(shí)會(huì)拋出一個(gè)異常提醒程序員出現(xiàn)了錯(cuò)誤需要更
正:
Studentstu=newstudent();
stu.Name=//非法數(shù)據(jù),名字怎能為空?
寫訪問器中有一個(gè)特殊的變量value必須特別注意,它代表J'外界傳入的值,例如以下
代碼向Naiue屬性賦值:
Studentstu=newStudent();
stu.Name="張三";
“張三”這一字串值將被保存到value變最中.供寫訪問器使用.
由上述例子可知,編寫屬性的方法如卜.:
(1)設(shè)計(jì)一個(gè)私有的字段用于保存屬性的數(shù)據(jù):
(2)設(shè)計(jì)get讀訪問器和set寫訪問器存取私有字段數(shù)據(jù)。
C#中還允許定義只讀屬性和只寫屬性。只讀屬性只行g(shù)et讀訪問器,而只寫屬性只有set
寫訪問器。
2.5深入理解類與對(duì)象
(1)類和對(duì)象的區(qū)別
清看示例程序UnderstandClassAndObject:
圖8示例程序UnderstandClassAndObject
如圖8所示,每次點(diǎn)擊主窗體上的“顯示另一個(gè)窗體”按鈕,都將在扉幕上顯示一個(gè)
“一模一樣”的輔助窗體。
在這個(gè)示例程序中,一共有兩個(gè)類:frmMain代表主窗體,frmOther代表輔助窗體。
在扉幕上顯示的窗體其實(shí)是fhiiMaiii和frinOther類創(chuàng)建的對(duì)象,主窗體上的按鈕堆擊
事件響應(yīng)代碼如下:
privatevoidbtnShowOtherForm_Click(objectsender.EventArg.-e)
(
〃創(chuàng)建輔助窗體對(duì)象
frmOtherfrm=newfmother();
〃顯示輔助窗體
frm.ShowO;
可以看到,每次點(diǎn)擊主窗體上的按鈕,都會(huì)創(chuàng)建一個(gè)輔助窗體fiinOther對(duì)象,這正是
在屏幕上出現(xiàn)多個(gè)輔助窗體的原因所在.
從這個(gè)示例程序可以得到以下重要認(rèn)識(shí):
?對(duì)象是以類為模板創(chuàng)建出來的.類與對(duì)象之間是一對(duì)多的關(guān)系。
?在C#中,使用new關(guān)鍵字創(chuàng)建對(duì)象。
?在程序中“活躍”的是對(duì)象而不是類.
在面向?qū)ο箢I(lǐng)域,對(duì)象有時(shí)又被稱為是“類的實(shí)例”,“對(duì)象”與“類的實(shí)例”這兩個(gè)
概念是等同的
(2)類的構(gòu)造函數(shù)
“1使用new關(guān)鍵字創(chuàng)建一個(gè)時(shí)象時(shí),?個(gè)特殊的函數(shù)被自動(dòng)調(diào)用,這就是類的構(gòu)造函
數(shù)(constructor),,
在C#中,類的構(gòu)造函數(shù)與類名相同,沒有返回值°
classA
(
〃類A的構(gòu)造函數(shù)
publicA()
類的構(gòu)造函數(shù)在以類為模板創(chuàng)建對(duì)象時(shí)被自動(dòng)調(diào)用。構(gòu)造函數(shù)?般用于初始化類的私有
數(shù)據(jù)字段。
(3)引用類型與值類型
NET將變量的類型分為“值類型”與“引用類型”兩大類。諸如mt和float之類的變
量屈丁?值類型,而“類'’類型的變量則胭于“引用類型
值類型變量與引用類型變域在使用上是有區(qū)別的。
值類型的變量一定義之后就馬上可用。比如定義“inti;"之后,變量i即可使用。
引用類型的變量定義之后,還必須用new關(guān)鍵字創(chuàng)建對(duì)象后才可以使用,我們在前面
一經(jīng)多次這樣使用過引用變量了。
在VisualStudio隨機(jī)文檔中,詳細(xì)地列出/每種數(shù)據(jù)類型屬于值類型還是引用類型(表
1):
表1C#的數(shù)據(jù)類型
類別說明
值類型簡單類型有符號(hào)整型:sbyte.short,iiit.long
無符號(hào)整型:byte,ushort.uint.ulong
Unicode字符:char
IEEE浮點(diǎn)型:float,double
高精度小數(shù):decimal
布爾型:bool
枚舉類型enumE{...)形式的用戶定義類邛
結(jié)構(gòu)類型stractS{...)形式的用戶定義類型
引用類型類類型所仃其他類型的最終基類:object
Unicode字符串:string
classC{...)形式的用戶定義類型
接口類型interfaceI{...}形式的用戶定義類型
數(shù)組類型一維和多維數(shù)組,例如in"]和加口
委托類型delegateTD(...)形式的用戶定義類型
值類型變量與引用類型變量的內(nèi)存分配模型也不?樣。為了理解清楚這個(gè)問題,讀者首
先必須區(qū)分兩種不同類型的內(nèi)存區(qū)域:線程堆棧(ThreadStack)和托管堆(ManagedHeap)。
每個(gè)正在運(yùn)行的程序都對(duì)應(yīng)著一個(gè)進(jìn)程(process),在一個(gè)進(jìn)程內(nèi)部,可以有一個(gè)或多
個(gè)線程(thread),每個(gè)線程都擁有一塊“自留地”,稱為“線程堆?!?,大小為1M.用廣保
存自身的一些數(shù)據(jù),比如函數(shù)中定義的局部變量:、函數(shù)調(diào)用時(shí)傳送的參數(shù)值等,這部分內(nèi)存
區(qū)域的分配與回收不需要程序員干涉。
所有值類型的變■都是在線程堆棧中分配的.
另?塊內(nèi)存區(qū)域稱為“堆(heap)”,在.NET這種托管環(huán)境下,堆由CLR進(jìn)行管理,所
以又稱為“托管堆(managedheap)”?
用new關(guān)鍵字創(chuàng)建的類的對(duì)象時(shí),分配給時(shí)象的內(nèi)存單元就位「托管堆中。
在程序中我們可以隨意地使用new關(guān)鍵字創(chuàng)建多個(gè)對(duì)象,因此,托管堆中的內(nèi)存資源
是可以動(dòng)態(tài)申請(qǐng)并使用的,當(dāng)然用完了必須歸還。
打個(gè)比方更易理解:托管堆相當(dāng)于一個(gè)旅館,K中的房間相當(dāng)于托管堆中所擁有的內(nèi)存
單元.當(dāng)程序員用new方法創(chuàng)建時(shí)象時(shí),相當(dāng)于游客向旅飾預(yù)訂房間,旅館管理員會(huì)先看
一下有沒有合適的空房間,有的話,就可以將此房間提供給游客住宿。當(dāng)游客旅途結(jié)束,要
辦理退房手續(xù),房間又可以為其他旅客提供服務(wù)了.
從表1可以看到,引用類型共有四種:類類型、接【1類型、數(shù)組類型和委托類型。
所有引用類型變量所引用的對(duì)象,其內(nèi)存都是在托管堆中分配的。
嚴(yán)格地說,我們常說的“對(duì)象變玳”其實(shí)是類類型的引用變量.但在實(shí)際中人們經(jīng)常將
引用類型的變量簡稱為“對(duì)象變量”,用它來指代所有四種類型的引用變量。在不致f?引起
混清的情況下,本書也采用了這種慣例。
在了解了對(duì)象內(nèi)存模型之后,對(duì)象變盤之間的相互賦值的含義也就清楚r.請(qǐng)看以下代
碼(示例項(xiàng)目ReferenceVariableForCS):
01classA
02{
03publicinti;
04)
05classProgram
06(
07staticvoidMain(string[]args)
08(
09Aa;
10a=newA();
11a.i=100;
12Ab=null;
13b=a;〃對(duì)象變量的相互賦值
14Console.WriteLine(Mb.+b.i);//b.i=?
151
16)
注意第12和13句。
程序的運(yùn)行結(jié)果是:
b.i-100;
請(qǐng)讀者思索一下:兩個(gè)對(duì)象變量的相互賦值意味著什么?
界實(shí)匕兩個(gè)對(duì)象變量的相互賦值意味著賦值后兩個(gè)對(duì)象變量所占用的內(nèi)存單元K
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年四川建筑職業(yè)技術(shù)學(xué)院馬克思主義基本原理概論期末考試模擬題附答案解析(奪冠)
- 2025年河曲縣幼兒園教師招教考試備考題庫附答案解析(奪冠)
- 2025年新疆科信職業(yè)技術(shù)學(xué)院單招綜合素質(zhì)考試題庫附答案解析
- 2025年貴州開放大學(xué)馬克思主義基本原理概論期末考試模擬題帶答案解析(必刷)
- 2025年福州黎明職業(yè)技術(shù)學(xué)院單招職業(yè)適應(yīng)性測試題庫附答案解析
- 2025年武漢工程大學(xué)馬克思主義基本原理概論期末考試模擬題帶答案解析(必刷)
- 2025年金陵科技學(xué)院馬克思主義基本原理概論期末考試模擬題附答案解析(必刷)
- 2025年麗水學(xué)院馬克思主義基本原理概論期末考試模擬題帶答案解析(必刷)
- 2025年平壩縣幼兒園教師招教考試備考題庫附答案解析(奪冠)
- 2025年南京機(jī)電職業(yè)技術(shù)學(xué)院馬克思主義基本原理概論期末考試模擬題及答案解析(必刷)
- 2026四川省物誠益商醫(yī)藥有限公司招聘業(yè)務(wù)員6人備考題庫完整答案詳解
- 安全教育培訓(xùn)管理制度及流程
- 2024-2025學(xué)年上學(xué)期南京初中語文九年級(jí)期末試卷
- 醫(yī)院消防安全宣傳教育
- 新高考數(shù)學(xué)之圓錐曲線綜合講義第26講外接圓問題(原卷版+解析)
- 中藥湯劑煎煮技術(shù)規(guī)范-公示稿
- 新版出口報(bào)關(guān)單模板
- 微型課題研究的過程與方法課件
- 藥學(xué)導(dǎo)論緒論-課件
- 14K118 空調(diào)通風(fēng)管道的加固
- 加油站財(cái)務(wù)管理制度細(xì)則
評(píng)論
0/150
提交評(píng)論