《CLR via C#》讀書筆記---06 類型和成員基礎

核心知識歸納圖
這裏寫圖片描述

6-1 類型中成員的本質

這裏寫圖片描述

  1. 顏色歸一
    編譯器支持了C#提供的各種各樣的類型成員,CLR對其一無所知,都是IL代碼

  2. 大小不同
    不同的類型成員因複雜度不同,編譯器映射出的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
- 儘量少的用虛方法
- 虛方法調用速度比普通速度慢
- 虛方法調用無法內聯,速度更慢一點
- 虛方法導致版本維護脆弱
- 版本維護的重點是穩定中謀發展,虛方法的修改會涉及多個依賴,有不穩定的因素。
- 多態重載的方法技巧
- 可以將複雜的邏輯抽取一個虛方法,其他普通重載調用該虛方法
- 子類重寫這個複雜的虛方法,調用父類相關重載的方法,最後調用的是子類的重寫的方法

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章