国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 編程 > .NET > 正文

在新的平臺(tái)上編程 ----微軟 .NET平臺(tái)系列文章之一(譯文/趙湘寧 )

2024-07-10 12:59:47
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

在新的平臺(tái)上編程
----微軟 .net平臺(tái)系列文章之一
譯文/趙湘寧
    一年多來(lái),我將注意力一直放在微軟的.net clr(公共語(yǔ)言運(yùn)行時(shí):common language runtime)平臺(tái)。在我看來(lái),今后大多數(shù)新的開(kāi)發(fā)都將面向這個(gè)平臺(tái),因?yàn)樗箲?yīng)用程序的開(kāi)發(fā)變得更容易、更簡(jiǎn)單。同時(shí),我還期望現(xiàn)有的應(yīng)用開(kāi)發(fā)能迅速移到.net平臺(tái)上來(lái)。
    為了幫助開(kāi)發(fā)人員掌握這個(gè)新的平臺(tái),本文以及以后的系列文章將專(zhuān)門(mén)針對(duì).net討論各種編程問(wèn)題。我將假設(shè)你已經(jīng)熟悉面向?qū)ο蟮木幊谈拍睢C恳黄恼碌膬?nèi)容都聚焦在非選定的特定公共語(yǔ)言運(yùn)行時(shí)編程主題上。所有.net開(kāi)發(fā)人員必須知道這些主題。
    當(dāng)展示代碼例子時(shí),我必須在支持.net clr 的多種語(yǔ)言中選擇一種。我決定使用c#。它是微軟設(shè)計(jì)的一種新語(yǔ)言。
    我的目的是介紹不同的編程主題并就如何實(shí)現(xiàn)它們?yōu)槟闾峁┮恍┫敕āK裕也幌胪暾拿枋雒恳粋€(gè)主題以及所有與之相關(guān)的細(xì)微差別。有關(guān)主題完整詳細(xì)的介紹請(qǐng)參考公共語(yǔ)言運(yùn)行時(shí)或者語(yǔ)言文檔。

真正的面向?qū)ο笤O(shè)計(jì)
    對(duì)于使用win32 sdk的編程人員來(lái)說(shuō),對(duì)大多數(shù)操作系統(tǒng)特性的訪(fǎng)問(wèn)時(shí)通過(guò)一組從動(dòng)態(tài)鏈接庫(kù)輸出的獨(dú)立函數(shù)實(shí)現(xiàn)的。這些獨(dú)立的函數(shù)從諸如c這樣的非面向?qū)ο笳Z(yǔ)言中非常容易調(diào)用。但對(duì)于一個(gè)新的開(kāi)發(fā)人員來(lái)說(shuō),要面對(duì)上千個(gè)表面上看來(lái)毫無(wú)關(guān)系的獨(dú)立的函數(shù)是相當(dāng)讓人畏懼的。更為困難的是許多函數(shù)名是以單詞“get”開(kāi)始的(如getcurrentprocess和getstockobject)。此外,win32 api已經(jīng)歷數(shù)年并且微軟添加了新的函數(shù),這些新函數(shù)依舊的函數(shù)相比。有相似的語(yǔ)義,但提供的特性有些差異。你常常能認(rèn)出較新的函數(shù),因?yàn)樗鼈兊拿衷瓉?lái)的函數(shù)名相似(象createwindow/createwindowex,createtypelib/createtypelib2以及我最喜歡的createpen/createpenindirect/extcreatepen
    所有這些問(wèn)題都使程序員覺(jué)得windows開(kāi)發(fā)很難。隨著.net平臺(tái)的出現(xiàn),微軟終于為叫苦不迭的開(kāi)發(fā)人員提供了一個(gè)完全面向?qū)ο蟮拈_(kāi)發(fā)平臺(tái)。平臺(tái)服務(wù)現(xiàn)在被分成為單獨(dú)的名字空間(如:system.collections,system.data,system.io,systemsecurity,system.web等等)并且每一個(gè)名字空間包含一組允許訪(fǎng)問(wèn)平臺(tái)服務(wù)的相關(guān)類(lèi)。
    因?yàn)轭?lèi)方法可以重載,行為差別不大的方法具有相同的名字,并且只有從原型中才能看出差別來(lái)。例如,一個(gè)類(lèi)可能提供三個(gè)不同版本的createpen方法。所有方法都做相同的事情:即創(chuàng)建一支筆。但是,每一個(gè)方法都有不同的參數(shù)集并且行為不太一樣。將來(lái)微軟還要?jiǎng)?chuàng)建第四個(gè)createpen方法并且與前面的類(lèi)方法配合默契。
    因?yàn)樗械钠脚_(tái)服務(wù)都通過(guò)這種面向?qū)ο蟮姆绞絹?lái)實(shí)現(xiàn),所以軟件開(kāi)發(fā)者應(yīng)該對(duì)面向?qū)ο蟮木幊逃兴斫狻C嫦驅(qū)ο蟮姆椒ㄟ€帶來(lái)了其它的一些特點(diǎn),如使用繼承和多態(tài)性很容易創(chuàng)建專(zhuān)門(mén)版本的基類(lèi)庫(kù)類(lèi)型。我再次強(qiáng)烈建議要熟練掌握這些概念,這對(duì)于使用微軟的.net框架很重要。

system.object
    在.net中,每一個(gè)對(duì)象都是從system.object派生而來(lái)。也就是說(shuō)下面的兩種類(lèi)型定義(使用c#)是相同的:

class jeff {
...
}



class jeff : system.object {
...
}

    因?yàn)樗袑?duì)象都是從system.object派生出來(lái)的,從而可以保證每一個(gè)對(duì)象具有最小的功能集。表一是system.object中的公共方法。
    公共語(yǔ)言運(yùn)行時(shí)需要所有的對(duì)象都要用new操作符創(chuàng)建(調(diào)用newobj il指令)。下列代碼示范了如何創(chuàng)建jeff類(lèi)型(已在前面聲明)的對(duì)象實(shí)例:
jeff j = new jeff("constructorparam1");

new操作符根據(jù)指定的類(lèi)型需要從堆中分配字節(jié)數(shù)來(lái)創(chuàng)建對(duì)象。它初始化對(duì)象的開(kāi)銷(xiāo)成員。每一個(gè)對(duì)象都會(huì)有一些公共語(yǔ)言運(yùn)行時(shí)用來(lái)管理對(duì)象的附加字節(jié),如對(duì)象的許表指針以及對(duì)同步快的引用。
    調(diào)用類(lèi)的構(gòu)造函數(shù)時(shí),傳遞的參數(shù)在new語(yǔ)句中指定(例子中是串"constructorparam1")。注意大多數(shù)語(yǔ)言會(huì)編譯構(gòu)造函數(shù)以便它們調(diào)用基類(lèi)構(gòu)造函數(shù),但這在公共語(yǔ)言運(yùn)行時(shí)中是不需要的。
    在new實(shí)現(xiàn)了所有我所提到的操作后,它返回新創(chuàng)建對(duì)象的引用。在例子代碼中,這個(gè)引用被存儲(chǔ)在變量j中,它的類(lèi)型是jeff。
    另外,new操作符沒(méi)有配對(duì)操作(delete)。即沒(méi)有方法顯式地釋放或銷(xiāo)毀對(duì)象。公共語(yǔ)言運(yùn)行時(shí)提供自動(dòng)地探測(cè)的垃圾回收環(huán)境,當(dāng)對(duì)象不再被使用或不再被訪(fǎng)問(wèn)時(shí)自動(dòng)地釋放和銷(xiāo)毀對(duì)象,有關(guān)這個(gè)主題將在下次的討論中提出。

數(shù)據(jù)類(lèi)型的強(qiáng)制轉(zhuǎn)換
    在編程過(guò)程當(dāng)中,對(duì)象從一個(gè)數(shù)據(jù)類(lèi)型到另一個(gè)數(shù)據(jù)類(lèi)型的強(qiáng)制類(lèi)型轉(zhuǎn)換是十分常見(jiàn)的。在這一部分,我將討論對(duì)象的強(qiáng)制數(shù)據(jù)類(lèi)型轉(zhuǎn)換規(guī)則。為此,先看下列代碼:

system.object o = new jeff("constructorparam1");

先前的代碼編譯通過(guò)并正確執(zhí)行是因?yàn)橛幸粋€(gè)隱含的強(qiáng)制類(lèi)型轉(zhuǎn)換。new操作符返回jeff的一個(gè)引用類(lèi)型,但o是一個(gè)system.object的引用類(lèi)型。因?yàn)樗械念?lèi)型(包括jeff類(lèi)型)都能被強(qiáng)制轉(zhuǎn)換為system.object,隱含的強(qiáng)制類(lèi)型轉(zhuǎn)換是成功的。但是,如果執(zhí)行下面的代碼,就會(huì)有編譯器錯(cuò)誤,因?yàn)榫幾g器不提供基類(lèi)型到派生類(lèi)型的強(qiáng)制類(lèi)型轉(zhuǎn)換。

jeff j = o;

為了能通過(guò)編譯,必須插入如下的顯式強(qiáng)制類(lèi)型轉(zhuǎn)換:
jeff j = (jeff) o;
現(xiàn)在就可以編譯通過(guò)并成功執(zhí)行。
再來(lái)看另外一個(gè)例子:

system.object o = new system.object();
jeff j = (jeff) o;

第一行創(chuàng)建了一個(gè)system.object類(lèi)型對(duì)象。第二行代碼試圖將system.object引用類(lèi)型轉(zhuǎn)換為jeff引用類(lèi)型。兩行代碼都能編譯通過(guò)。但是在執(zhí)行的時(shí)候,第二行代碼產(chǎn)生一個(gè)invalidcastexception異常,如果捕獲不到這個(gè)異常,將強(qiáng)制應(yīng)用程序終止。

當(dāng)?shù)诙写a執(zhí)行時(shí),公共語(yǔ)言運(yùn)行時(shí)查證o所指的對(duì)象就是jeff類(lèi)型對(duì)象(或任何jeff派生類(lèi)型)。如果是,則公共語(yǔ)言運(yùn)行時(shí)允許強(qiáng)制類(lèi)型轉(zhuǎn)換。否則,如果o所指的對(duì)象與jeff類(lèi)型無(wú)關(guān),或是一個(gè)jeff的基類(lèi),則公共語(yǔ)言運(yùn)行時(shí)會(huì)預(yù)防這種不安全的強(qiáng)制類(lèi)型轉(zhuǎn)換并產(chǎn)生invalidcastexception異常。

c# 使用as操作符提供另一種方法來(lái)實(shí)現(xiàn)強(qiáng)制類(lèi)型轉(zhuǎn)換:

jeff j = new jeff(); // 創(chuàng)建一個(gè)新的jeff 對(duì)象
system.object o = j as system.object; // 強(qiáng)制轉(zhuǎn)換 j 為一個(gè)system.object對(duì)象
// 現(xiàn)在o 指jeff 對(duì)象

as操作符試圖強(qiáng)制轉(zhuǎn)換一個(gè)對(duì)象為指定的類(lèi)型。但與通常的強(qiáng)制轉(zhuǎn)換不一樣,如果對(duì)象的類(lèi)型強(qiáng)制轉(zhuǎn)換不成功,結(jié)果會(huì)是null,as操作符決不會(huì)擲出異常。當(dāng)引用有毛病的強(qiáng)制類(lèi)型轉(zhuǎn)換發(fā)生時(shí),將產(chǎn)生nullreferenceexception異常。下列代碼示范了這種情況。

system.object o = new system.object(); //創(chuàng)建一個(gè)新的object 對(duì)象
jeff j = o as jeff; //強(qiáng)制轉(zhuǎn)換 o 為一個(gè)jeff對(duì)象
// 上面的強(qiáng)制轉(zhuǎn)換失敗:不會(huì)有異常擲出,而j會(huì)被置為null

j.tostring(); // 訪(fǎng)問(wèn)j時(shí)產(chǎn)生一個(gè)nullreferenceexception 異常

除了as操作符以外,c#還提供一個(gè)is操作符。它檢查是否一個(gè)對(duì)象實(shí)例與給定的類(lèi)型兼容并判斷結(jié)果是true或是false。is操作符不會(huì)產(chǎn)生異常。

system.object o = new system.object();
system.boolean b1 = (o is system.object); // b1 是 true
system.boolean b2 = (o is jeff); // b2 是 false

注意,如果對(duì)象引用是null,is操作符總是返回false,因?yàn)榈貌坏綄?duì)象來(lái)檢查其類(lèi)型。
為了肯定你理解了剛才所說(shuō)的內(nèi)容,假設(shè)下列兩各類(lèi)定義存在。

class b {
int x;
}

class d : b {
int x;
}

現(xiàn)在,參見(jiàn)圖二看看哪一行代碼通過(guò)編譯并執(zhí)行成功(es),哪一行代碼導(dǎo)致編譯器錯(cuò)誤(ce),哪一行代碼導(dǎo)致公共語(yǔ)言運(yùn)行時(shí)錯(cuò)誤(re)。

集合與名字空間
    類(lèi)型集可以被分組成集合(一個(gè)或多個(gè)文件集)并且被展開(kāi)。在一個(gè)集合中可以只存在單獨(dú)的名字空間。對(duì)應(yīng)用程序開(kāi)發(fā)人員來(lái)說(shuō),名字空間就像有關(guān)聯(lián)的類(lèi)型的邏輯分組。例如,基本類(lèi)庫(kù)集合包含許多名字空間。system名字空間包括object基類(lèi)型、byte、int32、exception、math和delegate之類(lèi)的核心低級(jí)類(lèi)型,而system.collections名字空間包括的類(lèi)型如aarrylist、bitaarry、queue和stack。

    對(duì)于編譯器來(lái)說(shuō),名字空間只不過(guò)是名字較長(zhǎng)的的類(lèi)型名,以及其唯一性是用句點(diǎn)分隔某些符號(hào)名來(lái)保證的。對(duì)于編譯器而言,system名字空間中的object類(lèi)型只不過(guò)是用一個(gè)叫做system.object的類(lèi)型來(lái)表示。同樣,system.collections名字空間中的queue類(lèi)型簡(jiǎn)單地用標(biāo)示符system.collections.queue來(lái)表示。
    運(yùn)行時(shí)引擎不知道關(guān)于名字空間的任何信息。當(dāng)你訪(fǎng)問(wèn)一個(gè)類(lèi)型時(shí),公共語(yǔ)言運(yùn)行時(shí)只需要知道完整的類(lèi)型名字以及哪一個(gè)集合包含這個(gè)類(lèi)型的定義,以便公共語(yǔ)言運(yùn)行時(shí)能正確加載集合,從而找到要訪(fǎng)問(wèn)的類(lèi)型并處理之。
    編程人員通常都想用最簡(jiǎn)練的方法來(lái)表達(dá)算法,但用完全限定名引用每一個(gè)類(lèi)類(lèi)型的話(huà)極其麻煩。因此,許多編程語(yǔ)言提供一條語(yǔ)句來(lái)指示編譯器添加各種前綴到類(lèi)型名,直到實(shí)現(xiàn)一個(gè)匹配。當(dāng)用c#編程時(shí),我經(jīng)常在源代碼的最前面是用下面的語(yǔ)句:

using system;

當(dāng)我在代碼中引用一個(gè)類(lèi)型時(shí),編譯器需要保證這個(gè)類(lèi)型被定義過(guò)并且我的代碼要以正確的方式訪(fǎng)問(wèn)這個(gè)類(lèi)型。如果編譯器不能找到指定的類(lèi)型,它試圖將“system.”添加到類(lèi)型名并檢查產(chǎn)生的類(lèi)型名字是否與現(xiàn)存的類(lèi)型名匹配。前面的代碼行允許我在代碼中使用object,并且編譯器將自動(dòng)將名字展開(kāi)為system.object。我肯定你能輕松想象這樣省去了多少鍵盤(pán)輸入。
當(dāng)進(jìn)行類(lèi)型定義的檢查時(shí),編譯器必須知道哪一個(gè)集合包含了這個(gè)類(lèi)型,以便這個(gè)集合的信息和類(lèi)型信息能被送到結(jié)果文件中。為了獲得集合信息,你必須將定義了任何引用類(lèi)型的集合傳給編譯器。
    正如你所設(shè)想的一樣,這種設(shè)計(jì)存在一些潛在的問(wèn)題。為了編程方便,你應(yīng)該避免創(chuàng)建名字沖突的類(lèi)型。但是在某些情況中,它完全不可能。.net鼓勵(lì)組件重用。你的應(yīng)用程序可以利用microsoft所創(chuàng)建的組件,同時(shí),你也可以用richter創(chuàng)建的另一個(gè)組件。這些公司的組件可能都提供了一個(gè)叫做foobar的類(lèi)型,-microsoft的foobar所做的事情與richter的foobar所做的事情完全不同。在這種情況下,你無(wú)法控制類(lèi)類(lèi)型的命名。為了引用microsoft的foobar,你使用microsoft.foobar,為了引用richter的foobar,你使用richter.foobar。
在下列的代碼中,對(duì)foobar的引用是不明確的。編譯器報(bào)告一個(gè)錯(cuò)誤也就罷了,但是實(shí)際上c#編譯器挑選foobar類(lèi)型的一種可能的情況;直到運(yùn)行時(shí)你才能發(fā)現(xiàn)問(wèn)題:

using microsoft;
using richter;

class myapp {
method void hi() {
foobar f = new foobar(); // ambiguous, compiler picks
}
}

為了排除這種不明確的引用,你必須顯式地告訴編譯器,你想創(chuàng)建哪一個(gè)foobar。

using microsoft;
using richter;

class myapp {
method void hi() {
richter.foobar f = new richter.foobar(); // 明確引用
}
}

另一種語(yǔ)句形式是允許你為單獨(dú)類(lèi)型創(chuàng)建別名,如果你只使用名字空間中的幾種類(lèi)型并且不想用所有的名字空間類(lèi)型污染整個(gè)名字空間的話(huà),這種方法很方便。下列代碼示范了另一種解決類(lèi)型不明確問(wèn)題的方法。

// 定義richterfoobar 為richter.foobar的別名
using richterfoobar = richter.foobar;

class myapp {
method void hi() {
richterfoobar f = new richterfoobar(); // 不會(huì)出錯(cuò)
}
}

   這種方法對(duì)于消除類(lèi)型歧義有用,但不盡人意的地方仍然存在。假設(shè)澳大利亞的飛鏢(boomerang)公司(簡(jiǎn)稱(chēng)abc)和阿拉斯加的船舶(boat)公司(也簡(jiǎn)稱(chēng)abc)兩家公司各自創(chuàng)建了一個(gè)類(lèi)型。可能兩家公司都創(chuàng)建了叫做abc的名字空間,在名字空間中包含一個(gè)叫做buyproduct的類(lèi)型。任何試圖開(kāi)發(fā)需購(gòu)買(mǎi)飛鏢和船舶應(yīng)用程序的人將會(huì)陷入麻煩,除非編程語(yǔ)言提供編程方法來(lái)區(qū)分兩家公司的集合-而不僅僅是兩家公司的名字空間。
不幸的是c#語(yǔ)言只支持名字空間,并不提供任何方式來(lái)詳細(xì)說(shuō)明集合。但實(shí)際上碰到這個(gè)問(wèn)題的時(shí)候并不多,屬于罕見(jiàn)問(wèn)題。如果是設(shè)計(jì)希望第三方使用的組件類(lèi)型。推薦在一個(gè)名字空間中定義類(lèi)型,以便編譯器輕松排除類(lèi)型問(wèn)題。事實(shí)上,應(yīng)該使用公司全名(不是只取首字母)作為最高級(jí)名字空間名來(lái)降低沖突的可能性。你能看到microsoft使用“microsoft”作為名字空間。
在代碼中寫(xiě)一個(gè)名字空間聲明來(lái)創(chuàng)建名字空間是一件很簡(jiǎn)單的事情。就像下面這樣:

namespace companyname { // companyname
class a { // companyname.a
class b { ... } // companyname.a.b
}

namespace x { // companyname.x
class c { ... } // companyname.x.c
}
}

    注意名字空間是隱含的公共類(lèi)型(public)。不能通過(guò)任何訪(fǎng)問(wèn)修飾符改變這一點(diǎn)。但可以在內(nèi)部的名字空間中定義類(lèi)型(不能在集合外面使用)或者在公共的名字空間中定義類(lèi)型(能被任何集合訪(fǎng)問(wèn))。名字空間只表示邏輯上的限制策略,可訪(fǎng)問(wèn)性和包裝是通過(guò)將名字空間放入一個(gè)集合來(lái)完成的。
    下一次的討論中,我將闡述所有.net編程人員必須掌握的簡(jiǎn)單數(shù)據(jù)類(lèi)型、引用類(lèi)型和數(shù)值類(lèi)型。對(duì)于每一個(gè).net程序員來(lái)說(shuō),透徹理解數(shù)值類(lèi)型是非常重要的。
發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 汤阴县| 连南| 沈丘县| 巴青县| 合阳县| 陆河县| 荥阳市| 吉林市| 射洪县| 元氏县| 黄浦区| 思茅市| 宝丰县| 中牟县| 奈曼旗| 大港区| 岑巩县| 古田县| 辽源市| 隆回县| 五河县| 巴中市| 峨眉山市| 太仆寺旗| 丰台区| 思茅市| 星子县| 长丰县| 泾源县| 阿巴嘎旗| 瑞安市| 宜宾县| 华坪县| 汉川市| 章丘市| 榆林市| 舟山市| 龙海市| 陇西县| 建德市| 石狮市|