---
# System prepended metadata

title: BuildSchool Week2/201118.6th
tags: [後端, BackEnd, C#, .Equals, CLR, stack&heap, .NET, object, Bill叔, 多載覆寫, Build School, 實質&參考, boxing, ILCode, JIT]

---

# 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]




