# BuildSchool Week2/201118.6th ###### tags: ==`C#`== ==`後端`== ==`BackEnd`== ==`Build School`== ==`.NET`== ==`Bill叔`== ==`CLR`== ==`ILCode`== ==`JIT`== ==`boxing`== ==`stack&heap`== ==`實質&參考`== ==`object`== ==`多載覆寫`== ==`.Equals`== <span style=color:#d10e96>$$"此節應該要會的"$$</span> - 什麼是 .Net Framwork - 什麼是 CLR, IL Code, JIT Compiler - 所謂的 native code(machine code) 是什麼? - 什麼是 ILDASM - EXE檔 與 DLL檔 的差別 - 能夠自己建立 .net 類別庫並放進別的專案當作參考 - (實質型別)value type 和 (參考型別)reference type 的差別是什麼?個包括哪些東西?而實質型別的內容與參考型別的內容各是什麼?差別在哪? - 什麼是 stack 什麼是 heap - 為什麼 實質型別用 ReferenceEquals 比較永遠是 false? - 在 new 參考型別物件的時候,存的記憶體不同,所以 ReferenceEquals 比較也是 false - 什麼是 object / 它與 class 的關係 - .Equals 和 .referenceEquals 是否一樣,藉由多載和覆寫修改的變化實例操作看得懂嗎? - boxing 與 unboxing 是什麼? - int 有沒有繼承 object ? 答案是有:在這!所以繼承這件事,到底繼承了什麼要知道 ![](https://i.imgur.com/aPPcdcN.png) - Object.Gettype() 和 Object.Equals(Object) 要會用 - 什麼是 null ? >[name=阿宏][time=Wed, Nov 18, 2020 8:19 PM][color=#d10e96] ## 助教日 1117 演算法 Stack Death-First-Search廣度優先搜尋:使用 Queue 結構 BFS 深度優先搜尋:使用 Stack 結構 走訪的意義是探索出最近的路徑(最佳解) *演算法的使用是要看他的情況 定義:在有限步驟內解決數學問題的方程式 基數節點vs偶數節點 --- # 從菜鳥程序猿到終極工程師 CH6 開始講解基礎觀念 * 今天講的這些.Net Framework的概念都可以運用到 .Net Core * .Net Framework 屬於一種**類別庫** > 組合語言 pop...jump...return....->初階語言 > 高階語言:C =>提供簡單的函式庫,再編譯成機器碼 > > C C++ 編譯完會直接變成語言 > Java 中間有CLR(中介層的虛擬機),幫忙處裡記憶體管理,所以不會直接接觸到作業系統 > * **Common Language Runtime(CLR)中繼碼程式** 1. 記憶體管理 2. 執行序管理 * IL Code 1. Microsoft Intermediate Language (MSIL)中繼語言 2. 與 CPU 無關的組合語言,會針對CPU做最佳化 3. 會進行兩次最佳化(第一次是c#編譯成IL code(release建置時期)時,第二次是將IL code編譯成**特定**CPU機器碼的時候) 4. Release 會進行最佳化,debug 不需要 > **Just-In-Time compiler(JIT)** =>在執行期將IL code編譯成Native Code (因為ILcode需要先在記憶體被翻譯成機器碼,只有第一次需翻譯成機器碼) MetaData 中繼資料 * **exe** - excute 可執行,提供 entry point 讓CLR呼叫 - exe檔就是 IL code - 有進入點可以獨立執行 * **DLL檔** - Dynamic Linl Library file,動態鏈結函式庫檔案 - library為自訂語言程式庫 * **組件** 部屬和管理程式碼程式的身份識別單位。一個組件可能有多個命名空間。或者一個命名空間散佈在不同組件。*慣例上一個專案的輸出檔就是一個組件。**未來在課堂上聽到同一個組件,就代表位於同一個專案*** ## 型別系統 * **Primitive Type** * ** Reference Type 參考型別** :*變數的內容是一個位址address* - 介面 Interface - 類別 Class - 委派 Delegate * **Vaglue Type 實值型別** - 結構 Structure - 列舉 Enum [有關介面、抽象、虛擬的補充](https://medium.com/@ad57475747/c-%E9%9B%9C%E8%A8%98-%E4%BB%8B%E9%9D%A2-interface-%E6%8A%BD%E8%B1%A1-abstract-%E8%99%9B%E6%93%AC-virtual-%E4%B9%8B%E6%88%91%E8%A6%8B-dc3c5878bb80) **物件Object** > Class類別可以視為是物件的藍圖,當類別被建立(New)時,就成為了一個Object。 - Thread 執行序 - - 物件是存在稱為「堆疊(Heap)」的特殊記憶體區塊 ```csharp= MyRectangle r1 = new MyRectangle(); MyRectangle r2 = r1; ``` 指向同一個 Heap 的內容 ### Object Class 萬物之父 * 隱含繼承 (ref struc例外) * 公開成員方法 Object.GetYype 取得執行個體的型別,回傳值為Type Class Object.Equals方法:表示自己與傳入物件的比較,繼承後可以重新改寫他 ?(cf. Equals()是使用者可以自己定義的) Ogject.ToString方法: >如果沒有覆寫 (override) 就會傳回這個執行個體型別的字串 * 公開靜態方法 Object.Equals > get hashcode 和 equals有很大的關係 (雜湊碼)若兩個不相等,代表equals一定為flase Object.ReferenceEquals ?比較參考型別的位址 --- > [name=阿宏][time=Wed, Nov 18, 2020 8:20 PM][color=#d10e96] ![](https://i.imgur.com/sRdTj2x.png) - 在 C# 裡一個物件放超過 2G ,就要小心了,有可能放不進去,因為會有記憶體空間的問題。 > exe 檔 和 dll 檔都是 IL code > dll 檔是 MVC(網頁的架構) > dll 和 exe 的差別在 dll 沒有 entry point(進入點),這個進入點就是決定能不能夠被獨立執行,所以 exe 才可以獨立執行 >第一次最佳化是在編譯的時候,第二次最佳化在 IL Code 編譯成特定 CPU 機器碼時,然而在第一次最佳化編譯的時候是建置的時候,但這時候如果是 debug 模式,並不會最佳化,release mode 才會最佳化。 ![](https://i.imgur.com/nP97S4y.png) --- ### 認識組件(Assembly) ![](https://i.imgur.com/UixX5qv.png) ![](https://i.imgur.com/VUQLI6x.png) ### ==因此,當日後聽到課堂上講同一個組件的時候,就代表是位於同一個專案中== # <center style=color:#BA5>"型別"</center> #### 分為三種: - primitive type - reference type - value type ## 所謂的 primitive type有三種講法:但基本上現階段不需理會 - 所有的 predefine 都是 - 所有的 predefine 去掉 object 都是 - 所有的 predefine 去掉 object 和 string 都是 ==int 就是一種 結構型別,而結構型別是一種實質型別== # Stack & Heap / 實質&參考 > 觀念釐清: #### int i = 1,i的內容一定是 1 #### string s = "abc",s 裡的內容不是 "abc",而是 "abc" 的地址 - 參考型別會在 managed heap 多出 overhead ![](https://i.imgur.com/p7IQpIk.png) ==*在這裡要注意!*== managed heap 的物體的排序上面是 sync block index 再來才是 type object pointer,而通常進入點會在中間,所以在 sync block index 會佔有記憶體。 > 上面 Bill叔的示意圖反了,請看下面 ### Bill叔說:考一個題目 倘若今天我做一個 class 是空的,但其實它會隱含繼承 object,然後這時候我什麼都不做,我 new 一個物件,那這個物件的大小有多大,如果在 32 位元的話,new1 就是 12 byte,如果在 64 位元的話, new1 就是 24 byte,會這樣是因為,存的時候在 managed heap 的位置的關係,進入點會卡在 type object pointer 和 sync block index 中間 ,所以前面一直都會預留 幾個 byte 的記憶體空間。 ```csharp= empty new1 = new empty(); class empty { } ``` ![](https://i.imgur.com/TKxteaZ.png) 32位元是 12bytes,64位元是 24bytes ![](https://i.imgur.com/jJspmFR.png) 參考型別會在 managed heap 多出 overhead ![](https://i.imgur.com/rJQOTLI.png) 在 new 的時候,會先產生物件,address 0x0100 ,再把 0x0100 推到運算堆疊區,在推到參考堆疊區 --- ### 所有東西都可以接 object `object xx = ` ==只有 ref struct 不能去接 object== --- ### 實質型別跟 heap 就無關了,因為它的處理都在 stack,舉例: ex: 你設計一個 int i = 10;,那你就只會在 stack 裡,但這個還是有地址,只是他的地址是 stack 的地址。 ### 關於 stack 的大略概念: 大概有分成: 三個區 - 放變數的區 - 放參數的區 - 運算堆疊的區(也就是會在這裡進進出出) ex: 當你在處裡記憶體的時候,假設一開始原本在 heap 有一個參考型別被設計,所以會在 heap 有記憶體位置,這時候你如果有一些程式的處理,使它要指派給實質型別,這是後就會從 heap 的記憶體位置複製推到 stack 的 運算堆疊區,進行各種運算(指派當然也是一種運算!),然後在把運行完後的內容放到,放變數的區,或是放參數的區。 --- 老師上課有講到, string 和 object 的比較,雖然在寫的時候我們都是用`==` 去寫來判斷,看起來都一樣,但是其實在 IL code 裡是不一樣的 - string 在比較的時候在 IL code 是呼叫 op_Equality, - object 在比較的時候在 IL code 是呼叫所謂的 ceq 來比較, ceq 的比較只有變數內容相等才會相等 - 虛擬方法,繼承後能重新被改寫 ## 關於 referenceEquals 和 Equals 兩個方法的比較, 最原本原本兩個都是比較 變數的內容, 但是 Equals 可以藉由多載的形式,再藉由 overrid(覆寫)去呼叫這個多載蓋掉原本的方法,我們就可以在多載裡修改成不是比較變數內容,可以改比其他的, 像是 ex:直接比 string 一不一樣。 --- 基本上繼承,指得是繼承執行個體成員 所以你 new 一個 class, 可以直接使用 object 的 Equals ![](https://i.imgur.com/0uGDfyf.png) --- ## 問題: 1. bject 是一種 class,而所有的 class 都是繼承 object,而所有的 class 都是參考型別,那 object 到底是"參考型別"還是"參考型別與實質行別"之上? Ans: object 在文件上是 class,可能是參考型別,再問問 >[name=阿宏][time=Wed, Nov 18, 2020 8:23 PM][color=#01a51a]