CLR 定義了兩種類型,ReferenceTypes引用類型 和 ValueTypes 值類型。我們定義的各種Class都是引用類型,而我們用的decimal int 之類是值類型。
他們有什么區別呢?為什么 CLR要搞出兩種類型出來呢?肯定是因為他們各有各的優點。我們會分別論述
首先 引用類型,我們知道 創建引用類型的實例 必須通過new 這個關鍵字,比如 說 Person p=new Person();
這個時候 會在托管堆中申請出一片空間出來,用來存放我們真正的這個對象,同時在棧中 會存放一個引用p 存放該對象在堆中的內存地址。也就是說 p中存放的是地址,我們管p叫做對對象的引用。
也就是說 我們沒創建一個引用類型的對象,都要通過new來申請空間,但是在堆中申請空間 比較慢而且損耗性能。所以CLR有了值類型的想法,值類型 就是把所有數據都存放在棧里面,因為棧比較快,所以性能會比較好。
比如 int num=3; 就在棧 內存中 有個變量num 它里面存的就不是什么內存地址 ,而是真正的數值3。
你可能會說,既然??欤俏覀兏纱喽挤旁跅@锖昧?。這也是行不通的。我們寫程序的時候會經常有賦值操作,比如
我們寫 Person p2=p; 也就是說我們 又定義了一個p2對象 ,指向原先的p對象。這個時候在內存中真正發生了呢,堆中并沒有創建一個新的對象,而是 有個新的p2引用指向原來的對象而已。p 和p2指向的是同一個對象。
而 對于 int num=3; int num2=num;而言 就要在棧中完整復制一個空間。這樣的話,如果本身對象體積比較大,經常復制的話,空間需要就太大了。而同樣對于引用類型,只不過是復制了內存地址而已。
所以 這兩種類型都是有其存在意義的。當然,上面說的這些并不代表只有這么多優點。
我們知道C#中所有對象 都繼承自 system.object。這一點不要有半點懷疑。那什么時候 分支出了值類型和引用類型兩種呢?
system.object有個抽象子類system.ValueType, 具體的struct Enum等都是繼承自這個抽象類,但是這些具體的值類型之后 卻是不可以再“遺傳”的,不可以再有子類,
就從這里 斷了根。 而引用類型則是從System.object直接往下繼承,(不經過system.ValueType),類可以有自己的子類,一直向下,綿延不絕。
關于引用類型 和值類型的賦值??聪旅娴氖纠?/p>
class 引用類型和值類型 { public static void Main(string[] args) { PersonClass p1 = new PersonClass(); p1.name = "shenwei"; p1.age = 23; p1.mobile = "xxxxx"; PersonStruct p2 = new PersonStruct(); Console.WriteLine(p2.age); p2.name = "zhangxiaomao"; p2.age = 23; p2.mobile = "yyyyy"; //重新定義兩個對象 PersonClass p3 = p1; //指向p1 PersonStruct p4 = p2; //復制P2 //當我們對 新的對象做修改時,原來的對象會改變嗎? p3.name = "changed"; p4.name = "changed"; Console.WriteLine(p1.name); Console.WriteLine(p2.name); Console.ReadKey(); } } public class PersonClass { public int age; public string name; public string mobile; } public struct PersonStruct { public int age; public string name; public string mobile; }
運行結果
那么當我們要定義自己的類型時,如何決定我們是定義成 引用類型 class 呢,還是定義成值類型 呢
有這么幾條原則
如果要定義成值類型,那 你的類型 一定不可以 繼承其他類型,也不可以被其他類型繼承,這是必須要遵守的,上面也講過 值類型 斷了根
還有就是 我們很少需要對 結構體中的字段進行修改。甚至 我們寫代碼的時候 習慣直接設置 結構體中的字段為readonly形式的,即只讀的。
我個人認為 結構體就是為了 更方便的使用 一整塊基本不變的數據而已。
那除了列的這種情況,基本都是定義成class了。
新聞熱點
疑難解答