在c#中有大量的值型別, int,char,float…等c#的預定義的基本型別都是值型別,這裡面string是乙個例外。值型別直接包含值,變數引用的位置就是值在記憶體中實際儲存的位置,儲存在稱為棧的記憶體區域內。引用型別和引用它們的變數指向資料儲存位置。引用型別並不直接儲存值,它們儲存的是對乙個記憶體位置的引用(記憶體位址),要去那個位置才能找到真正的資料。引用型別指向的記憶體區域稱為堆。
我們需要使用自定義的型別時,自定義的引用型別很常用,就是我們常用的「類」。在這裡要提一下自定義的值型別,一種是「結構」,另外一種是「列舉」。• c++中的結構是多餘的東西,僅僅為了相容c而存在。c#中的結構與類有許多實質的區別,結構是輕量級的自定義資料型別,其資料儲存於棧中。
比較專案
struct
class
1. 儲存位置
棧託管堆
2. 變數賦值為null
不能可以
3. 繼承與派生
不支援支援
4. 定義無參建構函式不能能
5. 建構函式初始化所有字段
必須不必
6. 用new來例項化乙個物件
不一定必須
7. 定義析構函式不能能
8. 物件複製
正本與副本無關
淺拷貝和深拷貝
9. 如何**
無需**
自動**機制
10. 引數傳送
按值傳送
按位址傳送
11. 使用初始化表
不能可以
12. 作為list元素能否修改
不能可以
c++中,結構和類幾乎是同義詞,區別只在於:結構的成員預設為公開的,類的成員預設為私有的。但是在c#中,結構和類的成員預設都是私有的。
下面用乙個**例項說明一下上述區別的表現,**選自《c#本質論4.0》,**清單8-1:
using system;
using system.diagnostics;
using system.componentmodel;
using system.text;
using system.collections.generic;
namespace myprocesssample
//error
//5. 建構函式初始化所有字段,如下面的初始化必須包括全部三個字段
public angle(int hours, int minutes, int seconds)
public int hours
}public int _hours;
public int minutes
}private int _minutes;
public int seconds
}private int _seconds;
public angle move(int hours, int minutes, int seconds)
}// declaring a class - a reference type
// (declaring it as a struct would create a value type
// larger than 16 bytes.)
class coordinate
public angle longitude
set
}private angle _longitude;
public angle latitude
set
}private angle _latitude;
}class myprocess
;angle ag4 = new angle ;//這裡說明struct也是可以使用初始化列表的,前提是這個欄位是公有的
angle ag5 = new angle(7, 3, 1);
angle ag6 = new angle(9, 9, 9);
listallags = new list() ;
console.writeline(allags[0].hours + "," + allags[1].hours + "," + allags[2].hours);
allags[0] = allags[1];
console.writeline(allags[0].hours + "," + allags[1].hours + "," + allags[2].hours);
allags[0] = ag5;
console.writeline(allags[0].hours + "," + allags[1].hours + "," + allags[2].hours);
coordinate cd5 = new coordinate ;
listallcds = new list() ;
console.writeline(allcds[0].latitude.minutes + "," + allcds[1].latitude.minutes);
allcds[0] = allcds[1];
console.writeline(allcds[0].latitude.minutes + "," + allcds[1].latitude.minutes);
allcds[0] = cd5;
console.writeline(allcds[0].latitude.minutes + "," + allcds[1].latitude.minutes);
//以下說明引用型別的賦值存在深拷貝,淺拷貝的問題,直接賦值相當於淺拷貝
coordinate cd6 = cd5;
console.writeline(cd6.longitude.hours + "," + cd5.longitude.hours);
cd6.longitude = new angle(999, 999, 999);
console.writeline(cd6.longitude.hours + "," + cd5.longitude.hours);}}
}
對第8條,物件的複製方式,struct的形式完全和常用值型別一樣,但是class的複製就涉及到深拷貝和淺拷貝,可具體參考本站其它博文(
第11條,第12條來自陳老師的講課資料,不過現在驗證來好象有點出入,比如第11條,如果struct裡有乙個公有的字段,那麼是可以使用初始化列表初始化的。第12條也是,當時陳老師是這麼講解的:
list中,元素只能用索引器來獲取,例如 a[i]。索引器返回的本是可讀可寫的元素,但struct元素是按值傳送的,修改返回值對於list中的元素毫無影響。例如,a[i] = a[j]; c#此時發出編譯錯誤,實在是提醒程式設計師別誤入陷阱。但元素如果是class的,返回值則是按位址傳送的,是乙個引用,修改其值就是修改list中的元素, a[i] = a[j]; 是允許的。
經過驗證,見上述**的第109-122行,這些都是可以實現的。或者我對這一段理解有問題,還有待於深入的**。
struct 型別適於表示 point、rectangle 和 color 等輕量物件。 儘管使用自動實現的屬性將乙個點表示為類同樣方便,但在某些情況下使用結構更加有效。 例如,如果宣告乙個 1000 個 point 物件組成的陣列,為了引用每個物件,則需分配更多記憶體;這種情況下,使用結構可以節約資源。 因為 .net framework 包含乙個名為 point 的物件,所以本示例中的結構命名為「coords」。
public struct coords
}
將較小的類宣告為結構,可以提高系統的處理效率。 C 學習筆記03 類與物件
公有 私有 保護成員 在關鍵字public後面宣告,它們是類與外部的介面,任何外部函式都可以訪問公有型別資料和函式 在關鍵字private後面宣告,只允許本類中的函式訪問,而類外部的任何函式都不能訪問 在關鍵字protected後面宣告,與private類似,其差別表現在繼承與派生時對派生類的影響不...
C 學習筆記16 結構體和類
結構體和類的區別 在做乙個專案時,使用了較多的結構體,並且存在一些結構體的巢狀,即某結構體成員集合包含另乙個結構體等,總是出現一些奇怪的錯誤,才終於下決心好好分析一下到底類和結構體有啥不同,雖然它們很相似,但確實有很大的不同,用不好難免出的問題會比較多,現總結一下 一 結構體和類非常相似 1,定義和...
c 學習筆記(四) 類和結構
類的預設訪問許可權是private 結構是public 該關鍵字修飾的變數可以在類的const方法中修改 class node 建議使用如下方式 正確 constref constref int ii i ii ci ii ri ii 錯誤 constref constref int ii 原因 效...