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

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

《.net編程先鋒C#》第九章 配置和調(diào)度(轉(zhuǎn))

2024-07-10 13:00:27
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友
第九章 配置和調(diào)度
在上一章,你學(xué)到如何創(chuàng)建一個(gè)通用語(yǔ)言運(yùn)行時(shí)(clr)組件,且如何在一個(gè)簡(jiǎn)單的測(cè)試應(yīng)用程序中使用它。雖然clr組件就要準(zhǔn)備裝載了,但你還是應(yīng)該思考以下技術(shù)之一:
。條件編譯
。文檔注釋
。代碼版本化

9.1 條件編譯
沒(méi)有代碼的條件編譯功能,我就不能繼續(xù)工作。條件編譯允許執(zhí)行或包括基于某些條件的代碼;例如,生成應(yīng)用程序的一個(gè)查錯(cuò)(debug)版本、演示(demo)版本或零售(release)版本。可能被包括或被執(zhí)行的代碼的例子為許可證代碼、 屏幕保護(hù)或你出示的任何程序。
在c#中,有兩種進(jìn)行條件編譯的方法:
。預(yù)處理用法
。條件屬性
9.1.1 預(yù)處理用法
在c++中,在編譯器開(kāi)始編譯代碼之前,預(yù)處理步驟是分開(kāi)的。在c#中,預(yù)處理被編譯器自己模擬—— 沒(méi)有分離的預(yù)處理。它只不過(guò)是條件編譯。
盡管c#編譯器不支持宏,但它具有必需的功能,依據(jù)符號(hào)定義的條件,排除和包括代碼。以下小節(jié)介紹了在c#中受支持的各種標(biāo)志,它們與在c++中看到的相似。
。定義符號(hào)
。依據(jù)符號(hào)排除代碼
。引起錯(cuò)誤和警告
9.1.1.1 定義符號(hào)
你不能使用隨c#編譯器一起的預(yù)處理創(chuàng)建“define 標(biāo)志:符號(hào):定義 ”宏,但是,你仍可以定義符號(hào)。根據(jù)某些符號(hào)是否被定義,可以排除或包括代碼。
第一種定義符號(hào)的辦法是在c#源文件中使用 #define標(biāo)志:
#define debug
這樣定義了符號(hào)debug,且范圍在它所定義的文件內(nèi)。請(qǐng)注意,必須要先定義符號(hào)才能使用其它語(yǔ)句。例如,以下代碼段是不正確的:

using system;
#define debug

編譯器將標(biāo)記上述代碼為錯(cuò)誤。你也可以使用編譯器定義符號(hào)(用于所有的文件):
csc /define:debug mysymbols.cs
如果你想用編譯器定義多種符號(hào),只需用分號(hào)隔開(kāi)它們:
csc /define:release;demoversion mysymbols.cs
在c#源文件中,對(duì)這兩種符號(hào)的定義分為兩行 #define 標(biāo)志。
有時(shí),你可能想要取消源文件中(例如,較大項(xiàng)目的源文件)的某種符號(hào)。可以用 #undef 標(biāo)志取消定義:
#undef debug
#define的“定義標(biāo)志:符號(hào): 定義”規(guī)則同樣適用于#undef: 它的范圍在自己定義的文件之內(nèi),要放在任何語(yǔ)句如using語(yǔ)句之前。
這就是全部有關(guān)用c#預(yù)處理定義符號(hào)和取消定義符號(hào)所要了解的知識(shí)。以下小節(jié)說(shuō)明如何使用符號(hào)有條件地編譯代碼。

9.1.1.2 依據(jù)符號(hào)包括和排除代碼
最重要的“if標(biāo)志:符號(hào):包括代碼”方式的目的為,依據(jù)符號(hào)是否被定義,有條件地包括和排除代碼。清單9.1 包含了已出現(xiàn)過(guò)的源碼,但這次它依據(jù)符號(hào)被有條件地編譯。

清單 9.1 利用 #if 標(biāo)志有條件地包括代碼

1: using system;
2:
3: public class squaresample
4: {
5: public void calcsquare(int nsidelength, out int nsquared)
6: {
7: nsquared = nsidelength * nsidelength;
8: }
9:
10: public int calcsquare(int nsidelength)
11: {
12: return nsidelength*nsidelength;
13: }
14: }
15:
16: class squareapp
17: {
18: public static void main()
19: {
20: squaresample sq = new squaresample();
21:
22: int nsquared = 0;
23:
24: #if calc_w_out_param
25: sq.calcsquare(20, out nsquared);
26: #else
27: nsquared = sq.calcsquare(15);
28: #endif
29: console.writeline(nsquared.tostring());
30: }
31: }

注意,在這個(gè)源文件中沒(méi)有定義符號(hào)。當(dāng)編譯應(yīng)用程序時(shí),定義(或取消定義)符號(hào):
csc /define:calc_w_out_param square.cs
根據(jù)“ if標(biāo)志:符號(hào):包括代碼”的符號(hào)定義,不同的 calcsquare 被調(diào)用了。用來(lái)對(duì)符號(hào)求值的模擬預(yù)處理標(biāo)志為#if、 #else和 #endif。它們產(chǎn)生的效果就象c#相應(yīng)的if 語(yǔ)句那樣。你也可以使用邏輯“與”(&&)、邏輯“或”(¦¦)以及“否”(!)。它們的例子顯示在清單9.2 中。

清單 9.2 使用#elif 在#if標(biāo)志中創(chuàng)建多個(gè)分支

1: // #define debug
2: #define release
3: #define demoversion
4:
5: #if debug
6: #undef demoversion
7: #endif
8:
9: using system;
10:
11: class demo
12: {
13: public static void main()
14: {
15: #if debug
16: console.writeline("debug version");
17: #elif release && !demoversion
18: console.writeline("full release version");
19: #else
20: console.writeline("demo version");
21: #endif
22: }
23: }

在這個(gè)“if標(biāo)志:符號(hào):包含代碼”例子中,所有的符號(hào)都在c#源文件中被定義。注意第6行#undef語(yǔ)句增加的那部分。由于不編譯debug代碼的demo版本(任意選擇),我確信它不會(huì)被某些人無(wú)意中定義了,而且總當(dāng)debug被定義時(shí),就取消demo版本的定義。
接著在第15~21行,預(yù)處理符號(hào)被用來(lái)包括各種代碼。注意#elif標(biāo)志的用法,它允許你把多個(gè)分支加到#if 標(biāo)志。該代碼運(yùn)用邏輯操作符“&&”和非操作符“!”。也可能用到邏輯操作符“¦¦”,以及等于和不等于操作符。

9.1.1.3 引起錯(cuò)誤并警告
另一種可能的“警告 標(biāo)志錯(cuò)誤 標(biāo)志”預(yù)處理標(biāo)志的使用,是依據(jù)某些符號(hào)(或根本不依據(jù),如果你這樣決定)引起錯(cuò)誤或警告。各自的標(biāo)志分別為 #warning和#error,而清單9.3 演示了如何在你的代碼中使用它們。
清單 9.3 使用預(yù)處理標(biāo)志創(chuàng)建編譯警告和錯(cuò)誤

1: #define debug
2: #define release
3: #define demoversion
4:
5: #if demoversion && !debug
6: #warning you are building a demo version
7: #endif
8:
9: #if debug && demoversion
10: #error you cannot build a debug demo version
11: #endif
12:
13: using system;
14:
15: class demo
16: {
17: public static void main()
18: {
19: console.writeline("demo application");
20: }
21: }

在這個(gè)例子中,當(dāng)你生成一個(gè)不是debug版本的demo版本時(shí),就發(fā)出了一個(gè)編譯警告(第5行~第7行)。當(dāng)你企圖生成一個(gè)debug demo版本時(shí),就引起了一個(gè)錯(cuò)誤,它阻止了可執(zhí)行文件的生成。對(duì)比起前面只是取消定義令人討厭的符號(hào)的例子,這些代碼告訴你,“警告 標(biāo)志錯(cuò)誤 標(biāo)志”企圖要做的工作被認(rèn)為是錯(cuò)誤的。這肯定是更好的處理辦法。
9.1.1.4 條件屬性
c++的預(yù)處理也許最經(jīng)常被用來(lái)定義宏,宏可以解決一種程序生成時(shí)的函數(shù)調(diào)用,而卻不能解決另一種程序生成時(shí)的任何問(wèn)題。這些例子包括 assert和trace 宏,當(dāng)定義了debug符號(hào)時(shí),它們對(duì)函數(shù)調(diào)用求值,當(dāng)生成一個(gè)release版本時(shí),求值沒(méi)有任何結(jié)果。

當(dāng)了解到宏不被支持時(shí),你也許會(huì)猜測(cè),條件功能已經(jīng)消亡了。幸虧我可以報(bào)道,不存在這種情況。你可以利用條件屬性,依據(jù)某些已定義符號(hào)來(lái)包括方法。:

[conditional("debug")]
public void somemethod() { }

僅當(dāng)符號(hào)debug被定義時(shí),這個(gè)方法被加到可執(zhí)行文件。并且調(diào)用它,就象
somemethod();

當(dāng)該方法不被包括時(shí),它也被編譯器聲明。功能基本上和使用c++條件宏相同。
在例子開(kāi)始之前,我想指出,條件方法必須具有void的返回類(lèi)型,不允許其它返回類(lèi)型。然而,你可以傳遞你想使用的任何參數(shù)。
在清單9.4 中的例子演示了如何使用條件屬性重新生成具有c++的trace宏一樣的功能。為簡(jiǎn)單起見(jiàn),結(jié)果直接輸出到屏幕。你也可以根據(jù)需要把它定向到任何地方,包括一個(gè)文件。

清單 9.4 使用條件屬性實(shí)現(xiàn)方法

1: #define debug
2:
3: using system;
4:
5: class info
6: {
7: [conditional("debug")]
8: public static void trace(string strmessage)
9: {
10: console.writeline(strmessage);
11: }
12:
13: [conditional("debug")]
14: public static void tracex(string strformat,params object[] list)
15: {
16: console.writeline(strformat, list);
17: }
18: }
19:
20: class testconditional
21: {
22: public static void main()
23: {
24: info.trace("cool!");
25: info.tracex("{0} {1} {2}","c", "u", 2001);
26: }
27: }

在info類(lèi)中,有兩個(gè)靜態(tài)方法,它們根據(jù)debug符號(hào)被有條件地編譯:trace,接收一個(gè)參數(shù),而tracex則接收n個(gè)參數(shù)。trace的實(shí)現(xiàn)直接了當(dāng)。然而,tracex實(shí)現(xiàn)了一個(gè)你從沒(méi)有見(jiàn)過(guò)的關(guān)鍵字:params。
params 關(guān)鍵字允許你指定一個(gè)方法參數(shù),它實(shí)際上接收了任意數(shù)目的參數(shù)。其類(lèi)似c/c++的省略參數(shù)。注意,它必須是方法調(diào)用的最后一個(gè)參數(shù),而且在參數(shù)列表中,你只能使用它一次。畢竟,它們的局限性極其明顯。
使用params 關(guān)鍵字的意圖就是要擁有一個(gè)trace方法,該方法接收一個(gè)格式字符串以及無(wú)數(shù)個(gè)置換對(duì)象。幸好,還有一個(gè)支持格式字符串和對(duì)象數(shù)組的 writeline方法(第16行)。
這個(gè)小程序產(chǎn)生的哪一個(gè)輸出完全取決于debug是否被定義。當(dāng)debug符號(hào)被定義時(shí),方法都被編譯和執(zhí)行。如果debug不被定義,對(duì)trace和tracex的調(diào)用也隨之消失。
條件方法是給應(yīng)用程序和組件增加條件功能的一個(gè)真正強(qiáng)大的手段。用一些技巧,你就可以根據(jù)由邏輯“或”(¦¦)以及邏輯“與”(&&)連接起來(lái)的多個(gè)符號(hào),生成條件方法。然而,對(duì)于這些方案,我想給你推薦c#文檔。

9.2 在xml中的文檔注釋
很多程序員根本不喜歡的一項(xiàng)任務(wù)就是寫(xiě)作,包括寫(xiě)注釋和寫(xiě)文檔。然而,有了c#,你就找到改變老習(xí)慣的好理由:你可以用代碼的注釋自動(dòng)生成文檔。
由編譯器生成的輸出結(jié)果是完美的xml。它可以作為組件文檔的輸入被使用,以及作為顯示幫助并揭示組件內(nèi)部細(xì)節(jié)的工具。例如, visual studio 7 就是這樣一種工具。
這一節(jié)專(zhuān)門(mén)為你說(shuō)明如何最好地運(yùn)用c#的文檔功能。該例子涉及的范圍很廣,所以你不能有這樣的借口,說(shuō)它過(guò)于復(fù)雜,以至很難領(lǐng)會(huì)如何加入文檔注釋。文檔是軟件極其重要的一部分,特別是要被其他開(kāi)發(fā)者使用的組件的文檔。
在以下小節(jié)中,文檔注解用來(lái)說(shuō)明requestwebpage 類(lèi)。我已分別在以下幾小節(jié)中做出解釋?zhuān)?br>。描述一個(gè)成員
。添加備注和列表
。提供例子
。描述參數(shù)
。描述屬性
。編譯文檔


9.2.1 描述一個(gè)成員
第一步,為一個(gè)成員添加一個(gè)簡(jiǎn)單的描述。你可以用  標(biāo)簽這樣做:
/// this is ....


每一個(gè)文檔注釋起始于由三個(gè)反斜杠組成的符號(hào)“///”。你可以把文檔注釋放在想要描述的成員之前:

/// class to tear a webpage from a webserver

public class requestwebpage

使用和 標(biāo)簽,為描述添加段落。用標(biāo)簽引用其它已有了注釋的成員。
/// included in the  class

增加一個(gè)鏈接到requestwebpage類(lèi)的描述。注意,用于標(biāo)簽的語(yǔ)法是xml語(yǔ)法,這意味著標(biāo)簽大寫(xiě)化的問(wèn)題,而且標(biāo)簽必須正確地嵌套。
當(dāng)為一個(gè)成員添加文檔時(shí),另一個(gè)有趣的標(biāo)簽是 。它允許你描述可能使讀者非常感興趣的其它話題。

///

前面的例子告訴讀者,他可能也想查閱system.net 名字空間的文檔。你一定要給超出當(dāng)前范圍的項(xiàng)目規(guī)定一個(gè)完全資格名。
作為許諾,清單9.5 包含 requestwebpage類(lèi)中正在工作的文檔的所有例子。看一下如何使用標(biāo)簽以及嵌套如何為組件產(chǎn)生文檔。

清單 9.5 利用 , , , and  標(biāo)簽描述一個(gè)成員

1: using system;
2: using system.net;
3: using system.io;
4: using system.text;
5:
6: /// class to tear a webpage from a webserver
7: public class requestwebpage
8: {
9: private const int buffer_size = 128;
10:
11: /// m_strurl stores the url of the webpage
12: private string m_strurl;
13:
14: /// requestwebpage() is the constructor for the class
15: ///  when called without arguments.
16: public requestwebpage()
17: {
18: }
19:
20: /// requestwebpage(string strurl) is the constructor for the class
21: ///  when called with an url as parameter.
22: public requestwebpage(string strurl)
23: {
24: m_strurl = strurl;
25: }
26:
27: public string url
28: {
29: get { return m_strurl; }
30: set { m_strurl = value; }
31: }
32:
33: /// the getcontent(out string strcontent) method:
34: /// included in the  class
35: /// uses variable
36: /// used to retrieve the content of a webpage. the url
37: /// of the webpage (includinghttp://) must already be
38: /// stored in the private variable m_strurl.
39: /// to do so, call the constructor of the requestwebpage
40: /// class, or set its property  to the url string.
41: ///
42: ///
43: ///
44: ///
45: ///
46: ///  
47: ///
48: ///
49:
50: public bool getcontent(out string strcontent)
51: {
52: strcontent = "";
53: // ...
54: return true;
55: }
56: }

9.2.2 添加備注和列表
標(biāo)簽是規(guī)定大量文檔的地方。與之相比, 只僅僅規(guī)定了成員的簡(jiǎn)短描述。
你不限于只提供段落文本(使用標(biāo)簽)。例如,你可以在備注部分包含bulleted(和有限偶數(shù))列表(list):

///
/// constructor
///  or
///
///
///

這個(gè)list有一項(xiàng)(item),且該item引用了兩個(gè)不同的構(gòu)造函數(shù)描述。你可以根據(jù)需要,任意往list item中添加內(nèi)容。
另一個(gè)在備注部分很好用的標(biāo)簽是。例如,你可以用來(lái)引用和描述傳遞給構(gòu)造函數(shù)的參數(shù):

/// stores the url from the parameter ///  in
/// the private variable .
public requestwebpage(string strurl)

在清單9.6中,你可以看到所有的這些以及前面的標(biāo)簽正在起作用。

清單9.6 為文檔添加一個(gè)備注和bullet list

1: using system;
2: using system.net;
3: using system.io;
4: using system.text;
5:
6: /// class to tear a webpage from a webserver
7: /// the class requestwebpage provides:
8: /// methods:
9: ///
10: /// constructor
11: ///  or
12: ///
13: ///
14: ///
15: ///
16: /// properties:
17: ///
18: ///
19: ///
20: ///
21: ///
22: ///
23: ///
24: public class requestwebpage
25: {
26: private const int buffer_size = 128;
27:
28: /// m_strurl stores the url of the webpage
29: private string m_strurl;
30:
31: /// requestwebpage() is the constructor for the class
32: ///  when called without arguments.
33: public requestwebpage()
34: {
35: }
36:
37: /// requestwebpage(string strurl) is the constructor for the class
38: ///  when called with an url as parameter.
39: /// stores the url from the parameter  in
40: /// the private variable .
41: public requestwebpage(string strurl)
42: {
43: m_strurl = strurl;
44: }
45:
46: /// sets the value of .
47: /// returns the value of .
48: public string url
49: {
50: get { return m_strurl; }
51: set { m_strurl = value; }
52: }
53:
54: /// the getcontent(out string strcontent) method:
55: /// included in the  class
56: /// uses variable
57: /// used to retrieve the content of a webpage. the url
58: /// of the webpage (includinghttp://) must already be
59: /// stored in the private variable m_strurl.
60: /// to do so, call the constructor of the requestwebpage
61: /// class, or set its property  to the url string.
62: ///
63: /// retrieves the content of the webpage specified in
64: /// the property and hands it over to the out
65: /// parameter .
66: /// the method is implemented using:
67: ///
68: /// the method.
69: /// the  method.
70: /// the method
71: /// the  method
72: /// the  method
73: /// the  property together with its
74: ///  method
75: /// the  method for the
76: ///  object.
77: ///
78: ///
79: ///
80: public bool getcontent(out string strcontent)
81: {
82: strcontent = "";
83: // ...
84: return true;
85: }
86: }

9.2.3 提供例子
要想說(shuō)明一個(gè)對(duì)象和方法的用法,最好的辦法是提供優(yōu)秀源代碼的例子。因此,不要詫異文檔注釋也有用于聲明例子的標(biāo)簽:  and 。 標(biāo)簽包含了包括描述和代碼的整個(gè)例子,而  標(biāo)簽僅包含了例子的代碼(令人驚訝)。
清單9.7 說(shuō)明如何實(shí)現(xiàn)代碼例子。包括的例子用于兩個(gè)構(gòu)造函數(shù)。你必須給getcontent方法提供例子。

清單.7 利用例子解釋概念

1: using system;
2: using system.net;
3: using system.io;
4: using system.text;
5:
6: /// class to tear a webpage from a webserver
7: ///  ...
8: public class requestwebpage
9: {
10: private const int buffer_size = 12


收集最實(shí)用的網(wǎng)頁(yè)特效代碼!

發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 晋江市| 汝州市| 星子县| 巴里| 乐清市| 微博| 武汉市| 巴林左旗| 若尔盖县| 平谷区| 灵丘县| 巩留县| 富锦市| 乌拉特后旗| 建水县| 蒙山县| 扶沟县| 凉城县| 佛教| 大荔县| 连云港市| 阿瓦提县| 威海市| 铁力市| 武隆县| 克拉玛依市| 东方市| 潼关县| 清苑县| 农安县| 黑龙江省| 周至县| 若羌县| 铜川市| 博兴县| 噶尔县| 陈巴尔虎旗| 望江县| 曲麻莱县| 光泽县| 琼海市|