C#/.NET公共型別系統(CTS)

2020-07-16 10:04:46
公共型別系統(Comnioii Type System, CTS)定義了什麼是型別,以及每個型別可以擁有的成員和行為。

之所以稱它是通用的,是因為它對所有 .NET 語言都適用。CTS 是保證 C# 語言型別安全的前提。

前邊已經說過,CTS 只是一個規範,並沒有限制它的實現方式。CLR 可以看作是 CTS 的一種實現,它符合上面給出的連結上的所有要求。其他的實現包括 Mono, Rotor 等。

下表列出了 .NET 中一些基礎名詞及縮寫,以及這些名詞之間的相互關係。

名詞 說明
VES(虛擬執行系統) 負責為某種語言在執行時提供一切必須的上下文和記憶體、執行緒管理、字串駐 留、垃圾回收、即時編譯等服務。CLR 是它的一個實現。可以用執行時(Runtime)代稱。一個 VES 的實現可以提供上面所說的所有服務,也可以只提供部分服務
IL(中間語言)  .NET 框架語言第一步編譯的目標語言。它會再通過 JIT 編譯器編譯為機器碼
CTS(公共型別系統) CLI 的一部分,描述了各種型別應該具有怎樣的行為以及可以擁有什麼樣的成員
CLS(公共語言規範) CTS 的一部分,描述了一個框架語言需要擁有的最小功能集
CLI(公共語言基礎設施) 上面所有的彙總。它包括了 VES、IL、CTS、CLS的定義,還規定了後設資料應該包括什麼等等。目前,主流的 CLI 實現有 .NET 編譯器、微軟 XNA、Rotor (即 Shared Source CLI)等等。可以在 ECMA334 和 ECMA335 這兩份檔案中找到 CLI 的全部內容

型別指的是集合{類,結構,介面,列舉,委託}中的任意一個成員。

型別(type)和 類(class)不同,後者是前者的一個特殊情況。

任何擁有某型別的值(value)稱為某型別的一個範例(instance)。

在 .NET 中,對任何值的使用(作為引數傳遞或操作)都需要首先明確這個值的型別是什麼。

介面和委託都是一種特殊的類,而結構可以看作一個輕量級的類。

型別可以被分為值型別(結構和列舉)以及參照型別(類、介面、指標、.字串、委託、陣列),沒有第三種情況。特別的,指標屬於參照型別。

型別可以擁有 0 或多個成員,這些成員可以簡單地分為欄位、方法和巢狀型別。

欄位成員包括:

1) 常數(const)

一個隱式為靜態和唯讀的成員。由於它一定是靜態的,所以它屬於類 型本身。

2) 欄位(field)和屬性(property)

刻畫型別的基本性質。靜態的欄位和屬性屬於型別本身。

屬性還分為無參屬性和有參屬性(索引器),並包括兩個方法。

3) 事件(event)

事件在物件以及其他相關物件之間實現了一個通知機制。

例如,利用按鈕提供的一個事件,可以在按鈕被單擊之後通知其他物件。

實際上也可以將其看作一種方法,只不過不能自定義。

其中,屬性和事件自帶的方法位於附加的後設資料中,無法自定義和修改。

方法成員包括:

1) 建構函式(constructor)和解構函式(destructor)

用於型別初始化和型別的垃圾回收。 建構函式又可以分為靜態的和範例的。

2) 方法(method)

型別的方法可以視為它提供的功能,分為靜態的和範例的。

3) 操作符過載

一種特殊的方法,它用於重寫操作符的定義。

可以在型別中定義其他型別,這稱為巢狀型別。例如,類中可以含有委託和另一個類。不過,巢狀型別的使用有很多限制。

CTS 也規定了某些型別只能擁有上述成員的一小部分而不是全部。例如,列舉型別不可以擁有自己的方法,屬性和事件。

C# 支援 6 種型別存取修飾符。存取範圍由大到小排序為:

1) public:沒有限制。

2) protected internal:只能在所在程式集、定義的型別或派生型別進行存取。

3) internal:只能在所在程式集存取。

4)  private protected: C# 7.2 新增的存取修飾符,等同於5和6中滿足任意一個。

5) protected:只能由定義的型別或派生型別進行存取。

6) private:只能由定義的型別進行存取。

所有修飾符都可以修飾型別成員,而對應於直接定義在名稱空間下面的型別,則只有 public 和 internal 是可以使用的(除非型別巢狀於另一個更大的型別中)。

顯然,為一個非巢狀類加上 private 和 protected 是毫無意義的。

所以,除了 public 和 internal,其他四種修飾符不能作用於非巢狀類。

由 internal 修飾的類中的方法只能被同程式集的其他物件存取。

如果一個程式集 A 中有一個 internal 的型別 B,它含有方法 C,那麼程式集 D 中的程式碼不能呼叫方法 C,即使 C 是 public 的。

因為型別 B 對於程式集 D 不可見。程式集 D 也可以定義自己的型別 B,它被視為和程式集 A 中的 B 不同。

型別的存取修飾符體現了封裝性,即開發者可以控制型別中哪些方法和成員對外界是否可見,從而令外界不需要知道它們永遠不會存取或呼叫的成員。

如果沒有指定存取修飾符,型別的存取修飾符預設為 internal,型別成員則預設為 private(都是限制最大的那個)。