最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

第 29 講:面向對象編程(一):面向對象和類的基本概念

2021-04-28 14:22 作者:SunnieShine  | 我要投稿

C# 里最有意思的一個體系化架構就是面向對象(Object-oriented)。什么是面向對象呢?

Part 1 面向對象是什么

在 C# 的世界里,我們除了前面的簡單的例子可以通過 C# 解決之外,還可以用一種體系化的架構來搞定一個復雜的項目,這個叫做面向對象。

面向對象是什么?面向對象是將世間萬物通過代碼的形式呈現(xiàn)和體現(xiàn)出來的一種編程范式(Programming Paradigm)。所謂的編程范式,你可以理解成編碼的不同風格和方式。比如,我可以把代碼寫成數(shù)學函數(shù)調(diào)用那樣的嵌套過程,這種叫函數(shù)式編程(Function-oriented Programming,簡稱 FP);我還可以把代碼寫成 C 語言那樣,用函數(shù)作為執(zhí)行單位、并依賴于順序結構、條件結構、循環(huán)結構和跳轉結構來完成項目編碼的過程,稱為面向過程編程(Procedure-oriented Programming,簡稱 PP);最后還剩下一種編程范式,就是面向對象編程了。這里的“對象”并不是指男女朋友,而是把世間萬物的個體稱為對象。

這三種編程范式,都可以完成同樣一個任務,但是從代碼的邏輯和代碼書寫體現(xiàn)來說,寫法是不同的。而 C# 是基于面向對象編程的語言,因而我們不得不學習面向對象編程這一個編程范式。

由于面向對象這個編程范式稍微復雜一些(比較體系化),因此內(nèi)容很多。在這個教程里,我們可能會分成非常多節(jié)的內(nèi)容給大家呈現(xiàn)和介紹,希望你慢慢來。

Part 2 類

2-1 類的概念

(Class)是貫穿面向對象的基本單位。和 C 語言的面向過程編程一樣,函數(shù)是貫穿面向過程的基本單位;而類則是面向對象的基本單位。

類是世間萬物的抽象,換句話說,如果我們要完成一個很復雜的項目,我們就得把這個項目里需要用到的所有物體用類呈現(xiàn)和體現(xiàn)出來。而類是一個整體,它用代碼寫出來,拿給別人看這段代碼的時候,它就好像在看說明書一樣:這個物體可以怎么操作、如何操作、什么時候操作。這就是類。

為什么叫類呢?你想一下,我們所有人,統(tǒng)稱叫人類。為什么叫人類呢?因為是人這個類別,因此叫人類。這個類就取自這里:我們將物體用代碼呈現(xiàn)出來的這個基本單位就稱為類,就是這個原因。

2-2 類的語法

我們使用關鍵字 class 來表示一個類。在 class 關鍵字后,緊跟一個標識符,這個名字就是這個代碼里體現(xiàn)出來的類的名稱,代表的世間萬物里究竟什么東西;后緊跟一個大括號,來表示這個類里的具體內(nèi)容(也就是我剛才說的“可以怎么操作”、“如何操作”和“什么時候操作”。

這是不是很熟悉?是的,這就是最開始我們沒有對其解釋的 Program。因為 C# 是基于面向對象的編程語言,因此我們不得不將 Main 方法(還有別的自己寫的方法)包裹在類里。就算是這個類沒有用,我們也得這么寫,因為基于面向對象嘛。

當然了,我們將 Main 方法寫到 Program 類,那么換句話說,這個 Main 方法是 Program 類的一個成員(Member)。

這一節(jié)的內(nèi)容我們只會接觸到方法這一種成員類型,成員還有別的類型,比如屬性、事件等等。這些類型的成員在這一節(jié)的內(nèi)容里說不到,因此我們先不管它們。

2-3 類和類的交互

另外,類是基本單位,因此我們需要書寫若干個類,來達到類和類之間的關聯(lián)。這里我們需要學習如何在類之間作調(diào)用和交互。

比如,我們擁有一個類、稱為 Algorithm,它存儲了一個叫做 BubbleSort 的方法,專門用來對一個數(shù)組進行排序操作:

然后,我們將在 Program 類里完成調(diào)用和交互。

請注意代碼的第 12 行(Algorithm.BubbleSort(arr); 這一行代碼)。這句話是通過 類名.方法名(參數(shù)) 的方式來完成不屬于這個類的方法的調(diào)用的。這里的小數(shù)點,我們稱為成員訪問符(Member Access Operator);在讀代碼的時候,我們可以翻譯成自然語言的“的”:Algorithm.BubbleSort 可讀作“Algorithm 類的 BubbleSort 方法”。

在自然世界里,如果我們要想理解這樣的代碼,我們可以認為

  • Algorithm 類表示和存儲算法的相關操作;拿給別人看的時候,別人就知道里面的成員都是跟算法相關的;

  • Program 類表示程序基本的操作行為,因此拿給別人看的時候,別人就知道這個類專門給程序服務(畢竟帶了 Main 方法嘛),他就不會拿著這個類干別的事情;

  • Algorithm 類的 BubbleSort 方法從名字上就可以看出是“冒泡排序”,因此對于一個老外來說,這個調(diào)用寫法就相當于 算法.冒泡排序。是不是寫成漢字更好理解呢?

  • 實際上,我們前面用到的 Console.WriteLine、Math.Sqrt 等等方法調(diào)用下,左邊的 ConsoleMath 都是類的名字;而后面的 WriteLineSqrt 自然就是這些類內(nèi)部的成員了。

另外,int.Parsestring.Concat 這些方法的前面用的是關鍵字;但不知道你忘了沒有,這些關鍵字是和 BCL 名等價的。因此,這些關鍵字最終會被翻譯和解析成 Int32、String 這些內(nèi)部的名稱。而實際上,String 也是 C# 里的一個類,只是它是系統(tǒng)提供的,而不是我們自己寫的,和 Console、Math 是一樣的;而 int 則稍微有點不一樣:它是一個結構。結構的內(nèi)容我們將放在“結構”一個章節(jié)里給大家介紹。不過你可以認為結構和類目前都是使用 名稱.方法 的方式來調(diào)用這些方法的,因此你不必太過擔心超綱的內(nèi)容,至少目前我們還用不到結構的知識點;另一方面,因為語法是相同的(都用 名稱.方法),所以其實很好理解。

2-4 如何給類單獨創(chuàng)建一個文件

前面的內(nèi)容足以幫助我們學習和理解面向對象的編程思維,但是我們在寫代碼的時候,總不可能一個文件里放若干個不同的類吧。如果類太多,就會導致程序的代碼文件過于臃腫。一來翻的時候不好看,二來是不方便后續(xù)拓展和整體代碼,因為都寫在一個文件里,如果一個類太大了怎么辦。

因此,這一節(jié)我想給大家介紹一下,如何用 VS 創(chuàng)建一個獨立的類的文件。將一個類存儲到一個文件里,不同的類放在不同的文件里,這樣就方便我們整理和查看每一個類。

我們先打開解決方案資源管理器,然后找到項目,點擊右鍵,依次選擇“Add”(添加)、“New Item...”(新項目……)。

然后,找到“Class”(類),然后在下方文件名的地方輸入類名(就是前面的 Algorithm),然后 .cs 部分保留不動(因為這個是 C# 的類文件的專屬后綴名),改成 Algorithm.cs 后點擊“Add”(添加)。

然后,文件創(chuàng)建好了之后,文件默認長這樣:

注意,上方的五條 using 指令目前都沒用,因此我們刪掉就行;而下面的這個類里是空白的,我們需要把前面的代碼粘貼進去;而 namespace 是用來控制命名空間的,這一點我們在最開始說過。在這里因為發(fā)揮不了作用,因此我們可以不要它。

總之,文件變成這個樣子。把代碼抄過來就行了。整體就是一個創(chuàng)建類文件的過程。

然后,要返回 Program 類的所在文件,還是在解決方案資源管理器里找到 Program.cs,雙擊它就可以了。

Part 3 訪問修飾符

修飾符(Modifier),指的是在類的聲明(class Program 這里),以及方法這些成員上追加的、不是返回值類型的別的關鍵字信息。比如在前面,publicstatic、private 還有最開始就知道的 unsafe 關鍵字,它們一旦寫到這些東西上,我們就可以稱為它們叫做修飾符。加在類的聲明上,我們就稱為類的修飾符;加在方法上,就稱為方法的修飾符。

修飾符分成兩類:訪問修飾符(Accessibility)和非訪問修飾符(Non-accessibility),下面我們分成這樣兩類來給大家介紹。

先來說一下訪問修飾符。所謂的訪問修飾符,本身沒有代碼層面的意義,它是用來控制成員的可訪問級別的。這么說也不明白,我們來詳細說明一下具體每一個訪問修飾符的用法,然后你自然就知道是干啥的了。

3-1 public 關鍵字

我們將 public 用于成員上,用來表達這個東西在任何時間任何地方都可以用。只要使用合適的語法(就是前面說的利用成員訪問符來寫),就可以隨便用。

可以看到,我們在 BubbleSort 方法上標記了這個關鍵字,這是為了干什么呢?這是為了告訴你,這個方法隨時都可以用。如果你沒有標記這個關鍵字的話(或者標記了別的訪問修飾符的話),這個方法就不可能隨時隨地都可以用了。所以換句話說,public 關鍵字的訪問級別最高:任何時候都可以用。

3-2 internal 關鍵字

要想理解 internal 關鍵字,我們需要介紹一下解決方案和項目之間的關系。

3-2-1 項目和解決方案的概念和邏輯關系

解決方案(Solution),指的是整個程序寫的所有代碼的整體;而項目(Project)則可以將不同的代碼分門別類地存放和歸置。解決方案是所有這個程序里的代碼的整體,那么項目可以包括同樣用途用法的代碼,因此解決方案比項目范圍更大;而項目則包含代碼文件,因此項目比文件的范圍大。

項目就是我們在解決方案資源管理器里,那個前面圖標是方框帶 C# 的這個項目??吹搅藛?,旁邊有一個三角形,點擊這個三角形,可以展開/折疊屬于整個項目里的代碼文件。

這里 TestProject 就是一個項目;而它上面的 Solution 'TestProject' 就是整個解決方案,其解決方案的名字就叫 TestProject,這里的單引號里的內(nèi)容。

一頭霧水是吧,為啥解決方案居然和項目名是一樣的?一般來說,因為解決方案和項目的關系是“解決方案 > 項目”。但實際上,可以劃等號:大多數(shù)時候,我們在教學和初學 C# 編程的時候,一個解決方案只需要容納一個項目就可以了。既然一個解決方案只包含一個項目,那么整個項目名稱就完全可以和解決方案的名字是一樣的,單純是為了簡單。如果取名不一致的話,可能你會覺得解決方案的代碼亂糟糟的。

3-2-2 internal 的實際意義

internal 關鍵字一般用在類的聲明之上(當然也可以用在成員上),這表示這個類或者這個成員,是整個項目里的任意位置可以用;但超出這個項目(比如這個解決方案里有倆項目,另外一個項目里調(diào)用這個成員或者類)的話,這個時候,你就“看不見”它了:或者換句話說,你就不可以用這個東西了。

比如這樣,我們創(chuàng)建了一個新的項目。然后使用此類。

因為創(chuàng)建新項目這個內(nèi)容我們沒有必要用,所以這里就不展開給大家講解怎么在同一個解決方案里創(chuàng)建新的項目了。

創(chuàng)建項目和創(chuàng)建類代碼文件的方式是一樣的,只是選擇的東西是 Add project 而不是 Add new item;而且在點選創(chuàng)建的時候,不是在項目上(因為項目里只能創(chuàng)建文件,項目不能嵌套項目),而是只能在解決方案上點右鍵選擇創(chuàng)建。

很遺憾,可以看到代碼上報錯了。它提示的文字是“'ANewClassInAnotherProject' is inaccessible due to its protection level”。翻譯過來就是,這個類因為訪問級別低的關系,你無法使用它。

這里演示給大家看,就是這么一個道理:如果用了 internal 關鍵字的話,類僅在這個項目里可以隨便用;超出了范圍就無法使用了。

3-3 private 關鍵字

最后一個關鍵字是 private。我們可以看到,目前我們就只有 Main 方法上用到了這個訪問修飾符。這個訪問修飾符指的是,這個成員僅在這個類里面隨便用;超出去的任何位置(不管是別的類還是別的項目),都不可以使用此成員。

可以看到,因為 Main 方法的特殊性,這個方法僅提供給系統(tǒng)自動調(diào)用,因而設置為 private 是最安全也是最正確的行為:因為我們禁止讓外部的任何一處使用和調(diào)用 Main 這個特殊的方法。

當然了,Main 方法本身是特殊的方法,因此你也別想著遞歸調(diào)用它,或者是在類的別處調(diào)用 Main 方法本身。雖然這個寫法編譯器并不會管你:

確實是允許的,但這樣很危險:因為 Main 本身就是系統(tǒng)特殊方法,你自己用指不定會出什么代碼的 bug 呢。如果你遞歸學習得并不是特別理想,這樣的程序必然會導致嚴重問題的出現(xiàn)。不過從語法上講,因為設置的 private 允許在類里的別處隨便使用它,因此語法是允許這么做的。

C# 的標準版一共有 5 種訪問修飾符,但目前只能講清楚這三種,剩下的兩種我們需要在講了“繼承”特性后,才能說??傊阆劝堰@三個記住就可以了。其中,最低的是 private,只能在類里隨便用。當然,也沒有比 private 還低的級別了,因為級別再低的話,就沒有意義了;最高的是 public,隨時隨地都可以用。

3-4 其它的一些問題

當然了,前文的代碼還有一些小的細節(jié)需要說明清楚,因此我們這里列出來給大家介紹一下。

3-4-1 類也是可以修飾訪問修飾符的

顯然,前面的類標記了 internal 就是一個典型的例子。但是,我們來思考一下,給類的聲明上標記 private 是不是可行的寫法?顯然,private class 的組合是不科學的,因為類是面向對象的基本單位,因此類和類之間是獨立的代碼塊。我們要使用這個類,至少也需要保證類本身是可以在項目里訪問。否則,這個類就失去了意義:比如說,我給類標記了 private,那么就說明類本身只能在這個類里可以用。這是個啥?整個解決方案代碼那么多,居然存在有一個類完全獨立開別的代碼,只能夠自己使用自己,是不是說不過去?

因此,類的訪問修飾符最低也必須是 internal,而且,類僅只能用 internalpublic 這兩種訪問修飾符。就算我們后面把剩下的兩個訪問修飾符都說了,類依舊只能用這倆訪問修飾符對訪問級別進行修飾。

3-4-2 類的訪問修飾符和成員的訪問修飾符不一致,怎么理解?

我們舉個例子:

比如上方這樣的代碼格式,類的修飾符是 internal,但 BubbleSort 這個成員卻用的是比 internal 大的訪問級別 public。那么這個 BubbleSort 到底能不能訪問呢?最終的訪問級別是怎么樣的呢?

實際上,套在內(nèi)部的 BubbleSort 會受到外部 internal 級別的影響,保證這個方法的級別是取 internalpublic 里較小的那個級別。換而言之,既然類都是 internal 的,那么里面設置的級別肯定得基于 internal 來作判斷,對吧。總不能里面成員的訪問基本比類的訪問級別還大,那就說不過去了。

代碼書寫上,內(nèi)部寫的是 internal 還是 public 都無所謂,因為最終取的還是 internal;但是實際上,寫 public 就是為了省事。因為我們這么設置訪問級別的話,假設有一天我想把 Algorithm暴露(Expose)出來給用戶用了的話,就不一定非得是項目內(nèi)的使用了;如果你內(nèi)部的成員設置的是 internal 的話,根據(jù)級別要取較小的原則,別的用戶還是用不了成員。因此,這么寫組合是為了以后代碼的可拓展性,是一個好的習慣。

總之:要注意兩點:

  • 成員的最終可訪問級別,是取的類的訪問級別和里面的成員的訪問級別的較小者;

  • 按照習慣,如果類需要修飾 internal 的話,那么成員依舊使用 public,除非這個成員本來就不是給外人用的。

3-4-3 訪問修飾符可以不寫嗎?

C# 里為了保護代碼的安全性,一般是取最小的原則:盡量越小越好。因此,C# 是做了這么一個代碼約定的:如果不寫的話,默認就是這個成員可訪問級別的最小的這種。舉個例子,類的最小訪問級別是 internal,因此如果不寫訪問修飾符到類的聲明上的話,我們就默認這個類是 internal 的;如果成員沒有書寫訪問修飾符的話,那么我們默認這個方法是只能在類里隨便用的,即 private 的。

所以,讓我們來總結一下這幾個訪問修飾符:

  • public 關鍵字:隨時隨地都可以用。

  • internal 關鍵字:只有當前的項目里可以用;而出了這個項目后,這個東西就不能用了;

  • private 關鍵字:只能用在類里面的成員,表示只能在這個類里隨便用;超出去的任何位置都是不能用的。

另外,訪問修飾符的默認情況如下:

  • 類的聲明上,如果缺省訪問修飾符,默認是 internal

  • 成員上,如果缺省訪問修飾符,默認是 private。

Part 4 static 修飾符

因為非訪問修飾符,我們就用到了 static,而 unsafe 這類修飾符我們在之前已經(jīng)介紹過,因此這一部分的內(nèi)容我沒有寫成“非訪問修飾符”,而是寫的“靜態(tài)修飾符”。

4-1 實例和靜態(tài)的概念

static 一詞對于初學者來說非常不友好,因為它并不是很好從單詞的字面意思上理解。方法是類的執(zhí)行核心,我們可通過 類.方法 的格式使用它,那么自然而然就意味著方法我們可以無憂無慮地使用它們,只要訪問修飾符級別合適,方法的調(diào)用肯定是得心應手的。

不過,C# 還存在一類成員,稱為實例成員(Instance Member)。和靜態(tài)成員不同,實例成員往往會和一個物體或個體做一個綁定。比如減肥、跑步等行為,如果我們要寫成代碼的話,就必然會和一個人的個體單獨進行綁定(因為跑步和減肥都是一個人自己的行為)。如果人的減肥和跑步這些行為我們依然使用 static 來表達的話,顯然就不合理了??梢詮拇a里看到,我們前面使用和利用的行為,都不需要依賴于個體就可以執(zhí)行:比如 int.TryParseConsole.WriteLine、Math.Sqrt。第一個是把字符串解析成整數(shù)的行為,它顯然并不依賴于任何一個整數(shù)個體;而控制臺打印文字到屏幕上的過程,也不是依賴于哪一個控制臺,因為我們就一個控制臺用來顯示內(nèi)容,因此它并不依賴于一個泛指的個體。你可能會問我,求平方根總是依賴于一個數(shù)值了吧!是的,但是 C# 代碼的思維是:求平方根是一個統(tǒng)一規(guī)范的操作流程,它是綁定一個數(shù)值“參與運算”,而并不是“依賴于”數(shù)值本身。另外,Math 這個類還包含了很多方法,可提供給我們使用(比如求絕對值啊、正弦啊、取對數(shù)什么的)。計算我們可以讓它按類型進行綁定來使用,就需要把這些東西寫進這個類型的類(或是之前說的結構)的代碼文件里。但是,這樣又會使得整個類型的代碼變得相當多。因此,利用靜態(tài)成員而不是實例成員的思維方式,可以避免類型變得很臃腫。

關于實例的用法和語法,我們將在下一節(jié)的內(nèi)容給大家介紹。它的內(nèi)容也是非常多,要慢慢來學才行。

4-2 讓我們現(xiàn)在再來理解靜態(tài)方法

說完靜態(tài)和實例的區(qū)別后,我們再回到頭看 static 方法,你就會輕松不少。我們之前寫了不少的代碼,比如求質(zhì)數(shù)之類的程序。我們再次把代碼放到這里。

請觀察代碼的修飾符。我們最開始就強制性讓大家添加 static 關鍵字。這是有道理的:首先,Main 方法并不依賴于什么東西,它是系統(tǒng)自動調(diào)用的方法,是一個特殊的方法,因此我們必須在 Main 上追加 static 關鍵字;而其它的方法,都是在 Main 里得到了調(diào)用。既然 Main 都是靜態(tài)的了,那么我們沒有理由給這些其它被調(diào)用方法讓他們改實例的:因為它們是 Main 調(diào)用的,Main 都不依賴于實體,那么調(diào)用的這些方法,肯定也不會依賴于實體對象才對。我總不能說,我擁有一個 Program 的實體對象,才能計算這些東西吧。顯然沒有必要也沒有意義(畢竟,一個 Program 的實體是什么,這我怎么理解都不知道)。因此,定義成靜態(tài)的方法,顯然是正確的思維。

靜態(tài)我們就先說到這里。

順帶一提,這些方法都是給 Main 方法服務的,所以肯定不能給別處用了,自然就沒有寫訪問修飾符。當然了,寫也最好寫 private,你說是吧。

Part 5 文檔注釋

為了幫助我們書寫代碼,和查看代碼的相關信息,C# 提供了一種機制,叫做文檔注釋(Documentation Comment)。文檔注釋可以直接將代碼的描述信息呈現(xiàn)到代碼貼士里,以便我們鼠標放到每個成員上查看信息的時候,可以直接看到描述文字。

當然,如下我們會介紹非常多的文檔注釋的相關寫法,但是有些我們用不上,就簡單說一下;有些重要的我們就寫詳細一點。

5-1 文檔注釋的架構

我們先來說一下文檔注釋的用途和架構。文檔注釋用三斜杠開頭:///,在斜杠后,書寫注釋文字。它們并不會影響程序的執(zhí)行,因為它們是注釋文字。但是,文檔注釋提供了一個規(guī)范的書寫格式,只要我們按照格式寫,你就可以發(fā)現(xiàn),這些注釋文字就會顯現(xiàn)在代碼貼士上。

圖上這個小條我們暫且稱它“代碼貼士”。一旦我們在上方追加敘述文字后:

你就會發(fā)現(xiàn),這段文字的描述信息就呈現(xiàn)上來了。只要我們鼠標放在 InputValue 上,我們就可以看到它。

文檔注釋是通過類似 XML 的擴展語法標記來完成說明的,它可以寫在類上,也可以寫在成員上。文檔注釋用到的標記非常多,但是都有自己的用途,因此有必要給大家說明清楚具體用法。

下面我們來說一下基本的零部件。

5-2 基本文檔注釋塊

5-2-1 summary

圖上就用到了 summary。我們寫上成對的 summary,前面用尖括號,后面也是尖括號,但里面的 summary 左側要加上一個斜杠,用來表示標記是結束的。在期間,我們書寫文字,這些文字是用來描述被注釋的對象(方法啊、類什么的)的基本信息用的。文字可以有很多,如果一行寫不下的話,可以換行書寫。

5-2-2 remarks

remarks 塊差不多,它也是描述文字,用來表示這個東西的基本信息的。不過區(qū)別在于,remarks 塊是可選的,你可以不寫 remarks,但 summary 是必須有的。remarks 是補充說明文字,比如說我們要對求質(zhì)數(shù)的核心方法寫文檔注釋的話,summary 塊的內(nèi)容可能是“計算一個數(shù),是否是一個質(zhì)數(shù)?!?;但 remarks 的文字則可能是“請注意,由于是計算質(zhì)數(shù),因此傳入的數(shù)字必須得是一個大于 1 的正整數(shù)”。

5-2-3 returns

如果方法具有返回值的話,我們可能需要用 returns 塊來表達這個方法的返回值到底返回了個什么。比如說,判別質(zhì)數(shù)的返回值一定是一個 bool 結果,那么 returns 塊里的內(nèi)容可能就是“一個 bool 類型的數(shù)值,用來表示是否是質(zhì)數(shù):是則返回 true,否則返回 false”。

5-2-4 paramparamref

param 塊是一個單標記的 XML 塊,它專門描述敘述一個參數(shù),以及參數(shù)的對應解釋。舉個例子,在 IsPrime 方法里,我們需要傳入一個 int 類型的數(shù)據(jù)。這個時候,我們可以在方法的文檔注釋里追加一行 <param name="number">The number to check.</param>,就可以達到描述參數(shù)的效果。

當然,因為是描述參數(shù)的文字,所以它不會直接呈現(xiàn)到代碼貼士里。你需要在調(diào)用的時候才看得見:

調(diào)用方:

可以看到,只有在輸入了這個左小括號 ( 后,才會提示這個文字信息。

當然了,我們只需要追加到文檔注釋里,因此我們不需要在意書寫 param 標記的具體位置。你可以把它放在最開始,也可以放在最后面。只要包含這個解釋文字,那么文字就會正常顯示到代碼貼士里。

接著,我們可以在文檔注釋的別處引用這個參數(shù)。舉個例子,我們在描述 number 參數(shù)的時候,可以類似前面講解 remarks 塊那樣,追加解釋文字,提示用戶在使用的時候建議使用大于 1 的正整數(shù)。不過,這個時候我們會用到 number 參數(shù)作為解釋的一部分:“請注意參數(shù) number 需要大于等于 2”。此時這個 number 你可以手寫到文檔注釋里,不過建議的格式是使用 paramref 這個單標記的塊。

例如我們提取出了這段文字,里面第 2 行里,就用到了這個寫法。

5-2-5 example

example 塊很少用到,它也不會在任何時候呈現(xiàn)到代碼貼士里。example 是追加到文檔注釋里,表示代碼使用的一些相關示例的。你可以在 example 塊里追加一些格式。

比如這樣。實際上,這里是可以直接擱代碼的,不過代碼塊我們將在稍后介紹到。

5-2-6 exception

很多時候,可能有方法需要自己產(chǎn)生異常(通過 throw-new 語句拋出一些異常)。這個時候,我們可以通過文檔注釋,提供給用戶,讓用戶在查看方法本身的時候,可以看到這個方法可能會在內(nèi)部產(chǎn)生的異常。

它的格式和 param 差不多,它的格式也是差不多的。不過這里,參數(shù)用到的是 name="" 的格式,而這里,我們寫的是 cref="",這一點需要你注意。

比如這樣寫,追加到文檔注釋里,表示這個方法可能會在輸入不合法的時候產(chǎn)生 FormatException 異常類型。不過在用戶查看的時候,注釋文字是看不見的,而是顯示成類似這樣:

5-3 內(nèi)聯(lián)文檔注釋塊

有一部分寫法,是內(nèi)聯(lián)到前面介紹的塊里的,并不是單獨寫的。下面介紹一些基本的寫法。

5-3-1 ccode

ccode 塊都是嵌入到 summary 啊、remarks 里使用的內(nèi)聯(lián)塊。它們表示一段代碼或者內(nèi)聯(lián)的代碼。比如我們現(xiàn)在在書寫這篇文章的時候,“summary 和普通單詞 summary”的區(qū)別在于,前者我們使用了內(nèi)聯(lián)代碼的渲染。我們也可以把這樣的東西寫進文檔注釋里。寫法是 <c>代碼</c>。比如說,前文描述 example 塊的時候,我們就會使用代碼來描述文字,幫助用戶會使用這些東西。

比如 bool result = IsPrime(17); 就可以寫成一個內(nèi)聯(lián)代碼塊。另外,如果這個內(nèi)聯(lián)的代碼較長的話,我們可以考慮單獨提行書寫,比如這樣:

比如這樣。

順帶一提,<see langword="for"/> 用的時候不多,但是很有趣。和前面寫 <see cref=""/> 格式的文字不同,這個 langword="" 里寫的往往都是一些關鍵字,這表示在渲染和顯示文檔注釋的時候,把這個文字按關鍵字的形式呈現(xiàn)出來。比如說,我們用的 VS 里把關鍵字顯示成藍色,那么文檔注釋里,如果寫了 <see langword=""/> 的話,那么這個里面的單詞就會呈現(xiàn)成藍色。

5-3-2 ui、ba

這個相比不用多說了。這個是 HTML 沿用下來的標記。u 是下劃線,i 是斜體,b 是加粗,而 a 則是超鏈接。

我們拿 a 標記來舉例說明用法。

比如這里第 6 行就是一段引用 a 標記的寫法。而查看代碼貼士的時候:

你就可以發(fā)現(xiàn),這個鏈接可以點。

5-3-3 para

para 塊就是作為一個段落呈現(xiàn)的。比如前文里,我們可以把它拆成兩個段落來呈現(xiàn):

這樣嵌套兩段文字就可以了。

5-3-4 list

最后最麻煩的是這個 list 塊。list 塊有三種用法,分別是“渲染表格”、“渲染有序列表”和“渲染無序列表”。我們挨個來說一下。

在之前的 IsPrime 函數(shù)里,我們介紹了返回值。但是返回值的描述并不詳細,因此我們可以列表來表達。上方的這個描述文字寫起來很丑,不過可以將就著看。

我們使用 <list type="table"></list> 一對標記來表達一個表格。里面是表格的具體內(nèi)容。接著,我們使用 item 標記來寫一行文字。表格只能由兩列構成,這個是文檔注釋限制了的,因為這里的表格僅用來表達“數(shù)值:意思”這樣的一組概念。

item 塊里,我們嵌套 termdescription 塊分別表示“數(shù)值:意思”的“數(shù)值”部分和“意思”部分。到時候,代碼貼士將我們這個表格渲染成這樣:

在最下方就可以看到顯示的表格。

前面我們說的是 list type="table",接著我們來說下別的值。list type="number" 表示渲染一個有序列表;而 list type="bullet" 則渲染一個無序列表。它們里面呈現(xiàn)項目的用法是一致的,所以我們一起說。

在呈現(xiàn)有序或無序列表的時候,我們里面就只需要嵌套一個單純的 item 塊就可以了。我們不需要在 item 里繼續(xù)嵌套 termdescription 塊,因為這倆是給表格提供渲染用的。

如果要寫若干項目,我們只需要挨個寫出來內(nèi)容(文字),直接丟進 item 里就可以了。

這樣就可以了。

5-3-5 seeseealso

see 塊和 seealso 塊用來引用除了參數(shù)之外的別的東西,比如說類啊、方法之類的。舉個例子。

可以從這個方法的文檔注釋里看到,我們內(nèi)嵌了一個 <see cref="string"/><see cref="IsPrime(int)"/>,這恰好表示我這里引用了類型 string 和方法 IsPrime,并且 IsPrime 帶了一個參數(shù)是 int 類型。

這么寫的作用是為了表達實際上真正的類和方法在哪里。如果你直接寫 stringIsPrime 的文本到注釋里的話,我們就無法通過純文本來反推出這個玩意兒的具體位置。而寫成 see 的話,當鼠標移動到寫文檔注釋的這個成員上、系統(tǒng)會彈出代碼貼士的時候,我們可以直接用鼠標單擊這個信息,就可以跳轉到對應的代碼位置上去。

點擊這里的 IsPrime 后,代碼就會自動跳轉到 IsPrime 方法那里去。

另外,seealsosee 差不多,只是 seealso 是單獨用的。它寫在最外面,表示在文檔注釋里用到的(用 see 塊引用了的)類型、成員信息。就好像你寫的論文里的“參考文獻”、文章里的“另請參考”這種東西。

5-4 文檔注釋的注釋

呃,我們甚至可以給文檔注釋本身寫一個注釋文字信息,來提供一些幫助程序員自己開發(fā)代碼的時候完善文檔注釋的幫助文字。它的格式和 HTML 的一樣,也是 <!-- 文字 -->。

?/// <!-- This paragraph is incomplete, waiting for developers finishing this. -->

文檔注釋的注釋是不呈現(xiàn)也不會渲染的,因此我們大大方方寫進去就可以了。

5-5 完整例子

總之,這里給大家提供文檔注釋的書寫規(guī)范:我們使用前面求質(zhì)數(shù)的程序給大家展示文檔注釋。


第 29 講:面向對象編程(一):面向對象和類的基本概念的評論 (共 條)

分享到微博請遵守國家法律
简阳市| 汝南县| 台东县| 林西县| 墨竹工卡县| 常宁市| 儋州市| 嘉义县| 游戏| 盖州市| 泸州市| 霍城县| 游戏| 延寿县| 安溪县| 巢湖市| 进贤县| 高唐县| 江安县| 沁阳市| 海口市| 崇信县| 宕昌县| 阳江市| 中江县| 化州市| 卫辉市| 龙江县| 无极县| 梁山县| 泗阳县| 永春县| 抚宁县| 遵义县| 方城县| 安阳市| 铜陵市| 浦江县| 克山县| 海城市| 北辰区|