核心知識歸納圖
6-1 類型中成員的本質
顏色歸一
編譯器支持了C#提供的各種各樣的類型成員,CLR對其一無所知,都是IL代碼大小不同
不同的類型成員因複雜度不同,編譯器映射出的IL代碼量也不盡相同
編譯器對各種成員用一種“公共數據格式”來區分,可以視爲是一種flag。編譯器解析flag生成不同的IL。
6-2 類型的可見性
類型的可見性修飾符僅有兩個:public && internal(default)
語義:供所有類型使用 && 供程序集內所有類型使用
當我試圖爲類型定義爲private時,編譯提示
- 感悟:沒有private修飾類型也是對的。實際中沒有孤立存在的類型。實現了一個功能勢必會讓人調用。除非兩種情況:一是沒有用的代碼;二是從Main到所有的功能都容納在一個類型中,想來也是恐怖。
【語法】
B中引用using System.Runtime.CompilerServices;
在B的任意一個類型的命名空間上面加上[assembly: InternalsVisibleTo(“A”)]
這樣A就可以見到B程序集中任意類型
語法參考 http://fwhyy.com/2010/11/csharp-a-friend-assembly/
6-3 成員的可訪問性
CLR定義的關鍵字有6個,C#映射了其中5個
這裏特別闡釋一下:protected internal,被這個關鍵字(這都兩個單詞了)修飾的成員,可以被任何程序集中該類型派生類 或 定義程序集中的類型訪問,這裏是或的關係,意思是兩者都可以。
CLR | C# | info |
---|---|---|
Private | private | 成員只能由定義類型或任何嵌套類型中的方法訪問 |
Family | protected | 成員只能由定義類型、任何嵌套類型中的方法、任何程序集的派生類型方法訪問 |
FamilyandAssembly | 無 | |
Assembly | internal | 成員只能由定義程序集中的方法訪問 |
FamilyorAssembly | protected internal | 成員只能由定義類型、任何嵌套類型中的方法、任何程序集的派生類型方法、定義程序集中的方法訪問訪問 |
Public | public | 成員只能由任何程序集的任何方法訪問 |
- 想訪問成員,其定義類型先可見(想喫糖,需要找到裝糖的盒子)。遇到成員是public訪問不了,也許原因就在這裏
- 成員訪問不到報的錯Exception有FiledAccessException && MethodAccessException
- 提倡顯示聲明成員可訪問性(隱式默認是限制最大的可訪問性)
- C#重寫不可以變更可訪問性;CLR允許重寫放寬
- 接口的成員必須是public,默認也是public
- 所以init的時候編譯器已經做了這部分工作,這也是上面爲什麼說“通常”
- 類型叫“可見性”,類型的成員叫”可訪問性”
- 我猜測:類型能看到就是能看到,很直接,叫“可見”,成員在類型之中,畢竟是包了一層,想想還是挺科學的。
- 這裏只是強調一下,雖然都用一個詞,不能說叫錯,但畢竟不專業,就像有些人對象和類型不分的叫。
- 類型的可見性和成員的可訪問性有必要謹慎定義嗎?
6-4 靜態類型
本質:sealed與abstract共同修飾
- 不能繼承、實現接口(abstract)
- 沒有.ctor(abstract)
- 不能創建實例(sealded)
- 成員皆靜態,不能作爲參數、字段、局部變量
當你若干時間後不記得這些特徵,這是正常的事情,只需要記得“靜態”,與類型實例相反
6.5 分部類型
- 使用“partial”關鍵字,可以將一個類、接口、結構定義在多個文件中(不可跨程序集)
- 本質:CLR對其一無所知
- 好處:
- 多個代碼文件可以讓多人同時編輯協作
- 代碼邏輯獨立整理
- 我們一個類中代碼多,想給他分分類別整理,除了抽出去以外,可以整理放在多個文件中
- WinForm中的disgner.cs和edit的地方就是一種使用
6.6組件、多態和版本控制
什麼是組件?
- 做一個筆記本屏幕需要的玻璃,我們可以稱它爲屏幕的組件;做一個筆記本需要的屏幕,我們可以稱它爲筆記本的組件;出售一個筆記本時外面的紙箱子,外面可以稱它爲完整出售筆記本的組件……
- 在開發中,一個字段、方法,可以是一個組件;一個控件、一個界面可以是一個組件;一個功能、一個模塊是一個組件……
- 在這裏組件特別指的是“Assembly程序集”。一個Assembly是一個Component。像我們開發時候用過的一些三方的dll,像Dev、Donetbar、FastReport、Log4、NPOI……這些我們只需要引用幾個組件就可以使用它們封裝的功能,這些是對外公用的組件,裏面包含了自己的開發信息,像版本號、公鑰……;像我們開發項目裏面的程序集,僅是私用,切割模塊,大多沒有定義那些開發信息
維護版本期間做些什麼?
像我現在從事的軟件開發,有些Realease期間就是發佈一些小的版本,沒有大功能,就是來修復堆積的bug和一些小功能的開發
切記的是”克己”,不要去修改大的東西,不要自己看着一個有點規模或邏輯複雜的模塊去重構,一方面時間是否夠;一方面改的依賴多那測試的複雜度也是翻倍;另一方面影響接下來的進度和計劃
- 尤其修改基類務必謹慎,原因無他,牽扯依賴多
.NET Framework中提供的版本號怎麼用?
主要和次要,代表某一個大的功能模塊開發;內部版本和修訂,代表在這個大的功能下不斷的修復和增強
- 例如v5.5.0.0中開發一個大的模塊【考勤功能】,那v5.5.2.1、v5.5.2.12就是在考勤的方面的完善,想開發一個報表功能就變成v5.6.0.0
- 這是當初設定的設計
現在不同的公司不一樣,只要能分清版本號就可以了。有的只用3位數字表達版本號;有的用奇偶數來表達不同含義的版本
什麼是版本變更?
- 已發佈軟件的代碼只要修改,那版本就算變更了。哪怕是沒有意義的改變;哪怕修改的就是一個字段;哪怕只是Review代碼的命名
版本控制C#提供的5個關鍵字
C# | info |
---|---|
abstract | 抽象,修飾的類無法構造實例,修飾的方法無法有主體 |
virtual | 這個成員可由派生類型重寫 |
override | 重寫基類的成員 |
sealed | 密封,修飾的類,無法被繼承;與override結合修飾的屬性和方法,其派生類無法重寫該屬性和方法 |
new | 被修飾的子類成員和基類同名的成員沒有關係,隱藏基類該成員 |
密封類中的虛方法調用性能大於非密封類中的虛方法。運行密封對象實例中虛方法,編譯器知道該實例被密封了,少走虛方法的那套繼承多態的路子,自然快了
====以下內容暫時保留,並不認同作者放在這裏的意圖,我會將其總結在第八章的方法中======
- 靜態方法是對象的方法
- 重載
- CLR支持的重載:方法名相同,返回值類型、參數類型或參數類型順序、個數不同
- C#支持的重載:返回值不計算入內
- 靜態方法、虛方法、普通方法,編譯器加入Flag做標記,對應生成不同的IL
- 儘量少的用虛方法
- 虛方法調用速度比普通速度慢
- 虛方法調用無法內聯,速度更慢一點
- 虛方法導致版本維護脆弱
- 版本維護的重點是穩定中謀發展,虛方法的修改會涉及多個依賴,有不穩定的因素。
- 多態重載的方法技巧
- 可以將複雜的邏輯抽取一個虛方法,其他普通重載調用該虛方法
- 子類重寫這個複雜的虛方法,調用父類相關重載的方法,最後調用的是子類的重寫的方法