本課主要在介紹 C# 之中兩大類型的型別(Type)
分別是 Value Type 與 Reference Type
針對這兩種類型在記憶體儲存的方式做稍微深入地介紹
教學影片
注意:影片有高畫質 720P 的選項,可以看得更清楚喔!
重點提示
1. C# 型別(Type) 依照存取方式不同一共分為三種:Value Type、Reference Type 與 Pointer Type
2. C# 變數裡的資料都是存放在記憶體(Memory)內的
3.「int (整數)」就是一種 Value Type。它會先在記憶體中尋找一個空間,標記為變數名稱,然後將我們指定的數值存入
4. 上一課建立的 Student Class 則是一種 Reference Type。宣告 Reference Type 的變數時,也會先在記憶體中尋找一個空間,標記為變數名稱,然後裡面則「存放物件的記憶體位置」。
5. 物件必須要透過「new Class名稱()」的方式建立,沒有指向任何物件的 reference(參考) 變數,則存放著「null」。
6. 物件都是存放在一個稱為「Heap(堆疊)」的特殊記憶體區塊
補充
Pointer 指標
有學過 C/C++ 程式語言的人相信都不陌生,而對部分的人來說,指標則是他們學習 C/C++ 的噩夢之一。指標是一種「專門存放記憶體位置」的變數。因為記憶體操作是一種非常危險的行為,而導致程式時常會不明地中斷。當然,如果對指標的行為有高度地了解,並且對程式使用記憶體的行為非常了解的話,就不會遇到這些錯誤。
一般來說,純物件導向的程式語言為了要隱藏背後複雜的操作行為,是不會給予使用者使用指標。例如 JAVA 的型別就只有兩種,Primitive Type 與 Class Type。但是 C# 則保留了指標這個型別,個人猜想可能是為了要延續 C/C++ 指標所扮演的重要性才留下來的。
練習
如果我們執行了下面的程式碼,最後對話框中會印出甚麼呢?(Student 為第 14、15 課編寫的 Student class)
Student s1 = new Student();
s1.Name = "小山";
s1.Grade = 3;
Student s2 = s1;
s2.Name = "小羊";
s2.Grade = 2;
Student s3 = s1;
s3.Name = "高光";
s3.Grade = 5;
Student s4 = s2;
s4.Name = "元整";
s4.Grade = 1;
MessageBox.Show(s4.Say());
執行看看驗證自己的答案吧~
相關資訊連結
內建型別資料表 (除了 object 與 string 外,表中的型別都是 value type)
http://msdn.microsoft.com/zh-tw/library/ya5y69ds.aspx
實質型別的所有類型
http://msdn.microsoft.com/zh-tw/library/s1ax56ch.aspx
作者已經移除這則留言。
回覆刪除我分別秀4個值S1-S4...答案都是最後的值(元整,1)....這邊很怪呢!是否能請小山老師解釋說一下~Q.Q?
回覆刪除只要是 Reference Type 的質~它都只會抓最後被修改的數?S1被S2和S3取代~S2又被S4取代~
所以全部的數都看最後取代的S4這樣說對嗎?那這個功能是拿來做什麼的呢?
結果是正確的,先跟你確認這點
刪除只要是 Reference Type 的變數,都只會存著物件的「記憶體位置」
在這個練習的例子之中
可以想成最初使用 new Student() 建立的物件是一棟房子 H
然後我使用 s1 去紀錄房子的地址
我去修改 s1.name, s1.grade 都是修改到 H 裡面的東西
接著 s2 = s1; 這行是把 s1 裡面存著的 H 的位置傳給 s2
也就是說,s2 也是紀錄 H 的位置
所以修改 s2.name, s2.grade 也是修改 H 的資料
你慢慢看下來會發現其實最後
s1, s2, s3, s4 都是記錄 H 的位置
而且我們透過 s1, s2, s3, s4 修改資料時
都是修改到 H 的資料
所以 H 最後的資料當然就是最後 s4 那段程式碼執行完的結果囉!
這時你如果在各自 s1.say()... 去看看資料的話
也都是在看「同一個物件」的資料
所以結果都會相同
作者已經移除這則留言。
回覆刪除本來一直對這部分很有疑惑,感謝小山的教學!
回覆刪除小山老師想請問一下object 與 string 這兩個行別不算是 value type的話那他們算是哪種type呢?
回覆刪除基本上,一般來說只要不是 value type
刪除通常都是 reference type
pointer type 只有在極少狀況下才使用
object 與 string 都是 reference type
刪除作者已經移除這則留言。
刪除感謝老師的講解
刪除謝謝小山老師!!這邊變成我的練功房了~XD
回覆刪除講解的很詳細唷~~
回覆刪除while(true)
Good !!!
終於把 class 和 new 搞懂了 ~~
heap == 堆積
stack == 堆疊
感覺 reference 運作的模式 跟 pointer 一模一樣
不知道 他們 差在哪裡 ~~~??? >< !!!
C# 通常不會使用到 pointer
刪除主要是 C++ 上面在用
兩者概念上很像
都是記錄某個記憶體位置
只是使用方式上跟底層實作不太相同而已
不過其實沒有在寫 C++ 的話就不太需要瞭解
謝謝小山~~
回覆刪除小山老師您好
回覆刪除可否向您請教String也是Reference Type,為何下列程式碼不會像class一樣發生Ref的結果呢?
String A = "";
String B = A;
B = "Ref";
MessageBox.Show(A);
請問你期望產生甚麼樣的結果呢?
刪除MessageBox.Show(A); 是空的值吧!!
刪除小山老師您好
回覆刪除可否向您請教String也是Reference Type,為何下列程式碼不會像class一樣發生Ref的結果呢?
String A = "";
String B = A;
B = "Ref";
MessageBox.Show(A);
你好:
刪除因為這段程式碼的效果跟課程中不同。
課程中是讓 s2 指向 s1 所指向的物件,然後透過這個位置去修改物件的內容。
可是在你提供的程式碼中,你並沒有修改 A 這個物件,反而只是更改 B 指向的物件而已。
在第二行中,你把 B 指向 A 物件。第三行則將 B 改成指向 "Ref" 這個物件。
因此並沒有修改到 A 本身的內容。
小山老師您好,
刪除這裡沒有修改到 A 這個物件,是因為字串跟一般的參考型別運作原理有點不同嗎?
一般參考型別
Student s =new Student();
透過 new 這個指令到heap中建立一個物件並把記憶體位置回傳給(ref);
字串
String A = "";
沒有new這個指令,所以不會直接到heap中建立一個物件,而是先到heap中尋找有沒有值相同的物件,如果沒有才建立一個新的物件並把記憶體位置回傳給A (ref);
String B = A;因為B和A的值相同所以指向同一個物件;
B = "Ref";因為Ref這個值是新的所以到heap中建立一個物件並把記憶體位置回傳給B (ref);
也就是說如果要讓A和B指向同一個物件並修改物件的值就要寫成,
String A = "";
String B = A="Ref";
研究了很久才看懂,覺得好像是這樣嗎?
如果老師有空,希望可以再更新~~
謝謝老師!!!
小山老師,請問影片中,3:32之處,b=20是否應該為a=20呢@@?
回覆刪除謝謝你的提醒~
刪除老師請問參考型別主要是參考的是class的實作
回覆刪除並不會一直堆疊很多資料占用記憶體對嗎??
這跟override有何不同呢??
override 跟 reference 是完全不同的概念哦~
刪除建議可以先看看 override 的課程
謝謝小山老師~
回覆刪除受益良多! 感謝小山老師
回覆刪除請問我想建議一個S5內容複製S1, 但是修改s5.name時,s1.name不會改變, 請問我要怎麼寫
回覆刪除Student s1 = new Student();
回覆刪除s1.Name = "小山";
s1.Grade = 3;
Student s2 = new Student();
s2.Name = s1.Name;
s2.Grade = s1.Grade;
MessageBox.Show(s1.Say());
MessageBox.Show(s2.Say());
s2.Name = "小羊";
s2.Grade = 2;
MessageBox.Show(s1.Say());
MessageBox.Show(s2.Say());
我叫小山 ,我是 3 年級的學生
刪除我叫小山 ,我是 3 年級的學生
我叫小山 ,我是 3 年級的學生
我叫小羊 ,我是 2 年級的學生
請問一下,
回覆刪除如果把這裏的所有教學都學完了,
距離把C#的所有功能精通差多少百份比左右?? (大約就可以了)
* 本人的目標是在UNITY用C#寫遊戲的