• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
    • 軟件測試技術
    • 軟件測試博客
    • 軟件測試視頻
    • 開源軟件測試技術
    • 軟件測試論壇
    • 軟件測試沙龍
    • 軟件測試資料下載
    • 軟件測試雜志
    • 軟件測試人才招聘
      暫時沒有公告

    字號: | 推薦給好友 上一篇 | 下一篇

    <展現C#> 第九章 配置和調度(rainbow 翻譯)

    發布: 2007-6-30 18:56 | 作者: admin | 來源: | 查看: 13次 | 進入軟件測試論壇討論

    領測軟件測試網 第九章 配置和調度

    在上一章,你學到如何創建一個通用語言運行時(CLR)組件,且如何在一個簡單的測試應用程序中使用它。雖然CLR
    組件就要準備裝載了,但你還是應該思考以下技術之一:
    。條件編譯
    。文檔注釋
    。代碼版本化

    9.1 條件編譯
    沒有代碼的條件編譯功能,我就不能繼續工作。條件編譯允許執行或包括基于某些條件的代碼;例如,生成應用程序
    的一個查錯(DEBUG)版本、演示(DEMO)版本或零售(RELEASE)版本?赡鼙话ɑ虮粓绦械拇a的例子為許可證代
    碼、 屏幕保護或你出示的任何程序。
    在C#中,有兩種進行條件編譯的方法:
    。預處理用法
    。條件屬性
    9.1.1 預處理用法
    在C++中,在編譯器開始編譯代碼之前,預處理步驟是分開的。在C#中,預處理被編譯器自己模擬—— 沒有分離的預
    處理。它只不過是條件編譯。
    盡管C#編譯器不支持宏,但它具有必需的功能,依據符號定義的條件,排除和包括代碼。以下小節介紹了在C#中受支
    持的各種標志,它們與在C++中看到的相似。
    。定義符號
    。依據符號排除代碼
    。引起錯誤和警告
    9.1.1.1 定義符號
    你不能使用隨C#編譯器一起的預處理創建“define 標志:符號:定義 ”宏,但是,你仍可以定義符號。根據某些符號
    是否被定義,可以排除或包括代碼。
    第一種定義符號的辦法是在C#源文件中使用 #define標志:
    #define DEBUG
    這樣定義了符號DEBUG,且范圍在它所定義的文件內。請注意,必須要先定義符號才能使用其它語句。例如,以下代碼
    段是不正確的:

    using System;
    #define DEBUG

    編譯器將標記上述代碼為錯誤。你也可以使用編譯器定義符號(用于所有的文件):
    csc /define:DEBUG mysymbols.cs
    如果你想用編譯器定義多種符號,只需用分號隔開它們:
    csc /define:RELEASE;DEMOVERSION mysymbols.cs
    在C#源文件中,對這兩種符號的定義分為兩行 #define 標志。
    有時,你可能想要取消源文件中(例如,較大項目的源文件)的某種符號?梢杂 #undef 標志取消定義:
    #undef DEBUG
    #define的“定義標志:符號: 定義”規則同樣適用于#undef: 它的范圍在自己定義的文件之內,要放在任何語句如
    using語句之前。
    這就是全部有關用C#預處理定義符號和取消定義符號所要了解的知識。以下小節說明如何使用符號有條件地編譯代
    碼。

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

    清單 9.1 利用 #if 標志有條件地包括代碼

    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: }

    注意,在這個源文件中沒有定義符號。當編譯應用程序時,定義(或取消定義)符號:
    csc /define:CALC_W_OUT_PARAM square.cs
    根據“ if標志:符號:包括代碼”的符號定義,不同的 CalcSquare 被調用了。用來對符號求值的模擬預處理標志為
    #if、 #else和 #endif。它們產生的效果就象C#相應的if 語句那樣。你也可以使用邏輯“與”(&&)、邏輯“或”
    (&brvbar;&brvbar;)以及“否”(。。它們的例子顯示在清單9.2 中。

    清單 9.2 使用#elif 在#if標志中創建多個分支

    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: }

    在這個“if標志:符號:包含代碼”例子中,所有的符號都在C#源文件中被定義。注意第6行#undef語句增加的那部分。
    由于不編譯DEBUG代碼的DEMO版本(任意選擇),我確信它不會被某些人無意中定義了,而且總當DEBUG被定義時,就取消
    DEMO版本的定義。
    接著在第15~21行,預處理符號被用來包括各種代碼。注意#elif標志的用法,它允許你把多個分支加到#if 標志。該
    代碼運用邏輯操作符“&&”和非操作符“!”。也可能用到邏輯操作符“&brvbar;&brvbar;”,以及等于和不等于操作
    符。

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

    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: }

    在這個例子中,當你生成一個不是DEBUG版本的DEMO版本時,就發出了一個編譯警告(第5行~第7行)。當你企圖生成
    一個DEBUG DEMO版本時,就引起了一個錯誤,它阻止了可執行文件的生成。對比起前面只是取消定義令人討厭的符號的例
    子,這些代碼告訴你,“警告 標志錯誤 標志”企圖要做的工作被認為是錯誤的。這肯定是更好的處理辦法。
    9.1.1.4 條件屬性
    C++的預處理也許最經常被用來定義宏,宏可以解決一種程序生成時的函數調用,而卻不能解決另一種程序生成時的任
    何問題。這些例子包括 ASSERT和TRACE 宏,當定義了DEBUG符號時,它們對函數調用求值,當生成一個RELEASE版本時,求
    值沒有任何結果。

    當了解到宏不被支持時,你也許會猜測,條件功能已經消亡了。幸虧我可以報道,不存在這種情況。你可以利用條件
    屬性,依據某些已定義符號來包括方法。:

    [conditional("DEBUG")]
    public void SomeMethod() { }

    僅當符號DEBUG被定義時,這個方法被加到可執行文件。并且調用它,就象
    SomeMethod();

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

    清單 9.4 使用條件屬性實現方法

    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類中,有兩個靜態方法,它們根據DEBUG符號被有條件地編譯:Trace,接收一個參數,而TraceX則接收n個參
    數。Trace的實現直接了當。然而,TraceX實現了一個你從沒有見過的關鍵字:params。
    params 關鍵字允許你指定一個方法參數,它實際上接收了任意數目的參數。其類似C/C++的省略參數。注意,它必須
    是方法調用的最后一個參數,而且在參數列表中,你只能使用它一次。畢竟,它們的局限性極其明顯。
    使用params 關鍵字的意圖就是要擁有一個Trace方法,該方法接收一個格式字符串以及無數個置換對象。幸好,還有
    一個支持格式字符串和對象數組的 WriteLine方法(第16行)。
    這個小程序產生的哪一個輸出完全取決于DEBUG是否被定義。當DEBUG符號被定義時,方法都被編譯和執行。如果DEBUG
    不被定義,對Trace和TraceX的調用也隨之消失。
    條件方法是給應用程序和組件增加條件功能的一個真正強大的手段。用一些技巧,你就可以根據由邏輯“或”
    (&brvbar;&brvbar;)以及邏輯“與”(&&)連接起來的多個符號,生成條件方法。然而,對于這些方案,我想給你推薦C#
    文檔。

    9.2 在XML中的文檔注釋
    很多程序員根本不喜歡的一項任務就是寫作,包括寫注釋和寫文檔。然而,有了C#,你就找到改變老習慣的好理由:
    你可以用代碼的注釋自動生成文檔。
    由編譯器生成的輸出結果是完美的XML。它可以作為組件文檔的輸入被使用,以及作為顯示幫助并揭示組件內部細節的
    工具。例如, Visual Studio 7 就是這樣一種工具。
    這一節專門為你說明如何最好地運用C#的文檔功能。該例子涉及的范圍很廣,所以你不能有這樣的借口,說它過于復
    雜,以至很難領會如何加入文檔注釋。文檔是軟件極其重要的一部分,特別是要被其他開發者使用的組件的文檔。
    在以下小節中,文檔注解用來說明RequestWebPage 類。我已分別在以下幾小節中做出解釋:
    。描述一個成員
    。添加備注和列表
    。提供例子
    。描述參數
    。描述屬性
    。編譯文檔


    9.2.1 描述一個成員
    第一步,為一個成員添加一個簡單的描述。你可以用 <summary> 標簽這樣做:
    /// <summary>This is .... </summary>


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

    /// <summary>Class to tear a Webpage from a Webserver</summary>

    public class RequestWebPage

    使用<para>和 </para>標簽,為描述添加段落。用<see>標簽引用其它已有了注釋的成員。
    /// <para>Included in the <see cref="RequestWebPage"/> class</para>

    增加一個鏈接到RequestWebPage類的描述。注意,用于標簽的語法是XML語法,這意味著標簽大寫化的問題,而且標簽
    必須正確地嵌套。
    當為一個成員添加文檔時,另一個有趣的標簽是<seealso> 。它允許你描述可能使讀者非常感興趣的其它話題。

    /// <seealso cref="System.Net"/>

    前面的例子告訴讀者,他可能也想查閱System.Net 名字空間的文檔。你一定要給超出當前范圍的項目規定一個完全資
    格名。
    作為許諾,清單9.5 包含 RequestWebPage類中正在工作的文檔的所有例子?匆幌氯绾问褂脴撕炓约扒短兹绾螢榻M件
    產生文檔。

    清單 9.5 利用 <summary>, <see>, <para>, and <seealso> 標簽描述一個成員

    1: using System;
    2: using System.Net;
    3: using System.IO;
    4: using System.Text;
    5:
    6: /// <summary>Class to tear a Webpage from a Webserver</summary>
    7: public class RequestWebPage
    8: {
    9: private const int BUFFER_SIZE = 128;
    10:
    11: /// <summary>m_strURL stores the URL of the Webpage</summary>
    12: private string m_strURL;
    13:
    14: /// <summary>RequestWebPage() is the constructor for the class
    15: /// <see cref="RequestWebPage"/> when called without arguments.</summary>
    16: public RequestWebPage()
    17: {
    18: }
    19:
    20: /// <summary>RequestWebPage(string strURL) is the constructor for the class
    21: /// <see cref="RequestWebPage"/> when called with an URL as parameter.</summary>
    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: /// <summary>The GetContent(out string strContent) method:
    34: /// <para>Included in the <see cref="RequestWebPage"/> class</para>
    35: /// <para>Uses variable <see cref="m_strURL"/></para>
    36: /// <para>Used to retrieve the content of a Webpage. The URL
    37: /// of the Webpage (including http://) 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 <see cref="URL"/> to the URL string.</para>
    41: /// </summary>
    42: /// <seealso cref="System.Net"/>
    43: /// <seealso cref="System.Net.WebResponse"/>
    44: /// <seealso cref="System.Net.WebRequest"/>
    45: /// <seealso cref="System.Net.WebRequestFactory"/>
    46: /// <seealso cref="System.IO.Stream"/>
    47: /// <seealso cref="System.Text.StringBuilder"/>
    48: /// <seealso cref="System.ArgumentException"/>
    49:
    50: public bool GetContent(out string strContent)
    51: {
    52: strContent = "";
    53: // ...
    54: return true;
    55: }
    56: }

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

    /// <list type="bullet">
    /// <item>Constructor
    /// <see cref="RequestWebPage()"/> or
    /// <see cref="RequestWebPage(string)"/>
    /// </item>
    /// </list>

    這個list有一項(item),且該item引用了兩個不同的構造函數描述。你可以根據需要,任意往list item中添加內
    容。
    另一個在備注部分很好用的標簽是<paramref>。例如,你可以用<paramref>來引用和描述傳遞給構造函數的參數:

    /// <remarks>Stores the URL from the parameter /// <paramref name="strURL"/> in
    /// the private variable <see cref="m_strURL"/>.</remarks>
    public RequestWebPage(string strURL)

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

    清單9.6 為文檔添加一個備注和bullet list

    1: using System;
    2: using System.Net;
    3: using System.IO;
    4: using System.Text;
    5:
    6: /// <summary>Class to tear a Webpage from a Webserver</summary>
    7: /// <remarks>The class RequestWebPage provides:
    8: /// <para>Methods:
    9: /// <list type="bullet">
    10: /// <item>Constructor
    11: /// <see cref="RequestWebPage()"/> or
    12: /// <see cref="RequestWebPage(string)"/>
    13: /// </item>
    14: /// </list>
    15: /// </para>
    16: /// <para>Properties:
    17: /// <list type="bullet">
    18: /// <item>
    19: /// <see cref="URL"/>
    20: /// </item>
    21: /// </list>
    22: /// </para>
    23: /// </remarks>
    24: public class RequestWebPage
    25: {
    26: private const int BUFFER_SIZE = 128;
    27:
    28: /// <summary>m_strURL stores the URL of the Webpage</summary>
    29: private string m_strURL;
    30:
    31: /// <summary>RequestWebPage() is the constructor for the class
    32: /// <see cref="RequestWebPage"/> when called without arguments.</summary>
    33: public RequestWebPage()
    34: {
    35: }
    36:
    37: /// <summary>RequestWebPage(string strURL) is the constructor for the class
    38: /// <see cref="RequestWebPage"/> when called with an URL as parameter.</summary>
    39: /// <remarks>Stores the URL from the parameter <paramref name="strURL"/> in
    40: /// the private variable <see cref="m_strURL"/>.</remarks>
    41: public RequestWebPage(string strURL)
    42: {
    43: m_strURL = strURL;
    44: }
    45:
    46: /// <remarks>Sets the value of <see cref="m_strURL"/>.
    47: /// Returns the value of <see cref="m_strURL"/>.</remarks>
    48: public string URL
    49: {
    50: get { return m_strURL; }
    51: set { m_strURL = value; }
    52: }
    53:
    54: /// <summary>The GetContent(out string strContent) method:
    55: /// <para>Included in the <see cref="RequestWebPage"/> class</para>
    56: /// <para>Uses variable <see cref="m_strURL"/></para>
    57: /// <para>Used to retrieve the content of a Webpage. The URL
    58: /// of the Webpage (including http://) 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 <see cref="URL"/> to the URL string.</para>
    62: /// </summary>
    63: /// <remarks>Retrieves the content of the Webpage specified in
    64: /// the property<see cref="URL"/> and hands it over to the out
    65: /// parameter <paramref name="strContent"/>.
    66: /// The method is implemented using:
    67: /// <list>
    68: /// <item>The <see cref="System.Net.WebRequestFactory.Create"/>method.</item>
    69: /// <item>The <see cref="System.Net.WebRequest.GetResponse"/> method.</item>
    70: /// <item>The <see cref="System.Net.WebResponse.GetResponseStream"/>method</item>
    71: /// <item>The <see cref="System.IO.Stream.Read"/> method</item>
    72: /// <item>The <see cref="System.Text.StringBuilder.Append"/> method</item>
    73: /// <item>The <see cref="System.Text.Encoding.ASCII"/> property together with its
    74: /// <see cref="System.Text.Encoding.ASCII.GetString"/> method</item>
    75: /// <item>The <see cref="System.Object.ToString"/> method for the
    76: /// <see cref="System.IO.Stream"/> object.</item>
    77: /// </list>
    78: /// </remarks>
    79: /// <seealso cref="System.Net"/>
    80: public bool GetContent(out string strContent)
    81: {
    82: strContent = "";
    83: // ...
    84: return true;
    85: }
    86: }

    9.2.3 提供例子
    要想說明一個對象和方法的用法,最好的辦法是提供優秀源代碼的例子。因此,不要詫異文檔注釋也有用于聲明例子
    的標簽: <example> and <code>。 <example>標簽包含了包括描述和代碼的整個例子,而 <code> 標簽僅包含了例子的代
    碼(令人驚訝)。
    清單9.7 說明如何實現代碼例子。包括的例子用于兩個構造函數。你必須給GetContent方法提供例子。

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

    1: using System;
    2: using System.Net;
    3: using System.IO;
    4: using System.Text;
    5:
    6: /// <summary>Class to tear a Webpage from a Webserver</summary>
    7: /// <remarks> ... </remarks>
    8: public class RequestWebPage
    9: {
    10: private const int BUFFER_SIZE = 12

    文章來源于領測軟件測試網 http://www.kjueaiud.com/


    關于領測軟件測試網 | 領測軟件測試網合作伙伴 | 廣告服務 | 投稿指南 | 聯系我們 | 網站地圖 | 友情鏈接
    版權所有(C) 2003-2010 TestAge(領測軟件測試網)|領測國際科技(北京)有限公司|軟件測試工程師培訓網 All Rights Reserved
    北京市海淀區中關村南大街9號北京理工科技大廈1402室 京ICP備10010545號-5
    技術支持和業務聯系:info@testage.com.cn 電話:010-51297073

    軟件測試 | 領測國際ISTQBISTQB官網TMMiTMMi認證國際軟件測試工程師認證領測軟件測試網

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>