所以針對值型別和引用型別這個問題,我展開了一系列的學習。下面是我的一些收穫,分享給大家。
在c#中的型別分為倆種: 值型別和址型別
注: 結構體屬於值型別
所有的類都屬於引用型別,包括介面。
值型別包括:數值型別,結構體,bool型,使用者定義的結構體,列舉,可空型別。
引用型別包括:陣列,使用者定義的類、介面、委託,object,字串,null型別,類。
值型別和引用型別的區別是什麼:
值型別的例項都被分配到執行緒棧當中,所有的引用型別例項都被分配在託管堆上
效能:
由於值型別例項的值是自己本身,而引用型別的例項的值是乙個引用,所以如果將乙個值型別的變數賦值給另乙個值型別的
變數,會執行一次逐字段的複製,將引用型別的變數賦值給另乙個引用型別的變數時,只需要複製記憶體位址。
例如下面的**:
再來乙個例子:
public class person
// 定義個name 屬性
public int age //定義個age 屬性
}public static class referenceandvalue
;person anders = new person ;
int age = zerocool.age;
zerocool.age = 22;
person guru = anders;// 這個用到了引用,引用了前面定義好的 類anders;
anders.name = "anders hejlsberg";
console.writeline("zerocool's age:\t", zerocool.age);
console.writeline("age's value:\t", age);
console.writeline("anders' name:\t", anders.name);
console.writeline("guru' name:\t", guru.name);}}
首先我們定義了乙個 person 類,毋庸置疑 這個類是引用型別
然後,我們宣告了兩個person類的例項物件,zerocool和anders,前面提到過,這兩個物件都被分配在堆上,而zerocool和anders本身其實只是物件所在記憶體區域的起始位址引用,換句話說就是指向這裡的指標。
我們宣告乙個值型別變數age,直接在初始化時把zerocool的age值賦給它,顯然,age的值就是25了
我們宣告age值型別變數,並將zerocool.age賦給它,編譯器在棧上分配了一塊空間,然後把zerocool.age的值填進去
但是引用型別就不一樣了,我們在宣告guy的時候把anders賦給它,前面說過,引用型別包含的是只想堆上資料區域位址的引用,其實就是把anders的引用也賦給guy了,因此這二者從此指向了同一塊記憶體區域,既然是指向同一塊區域,那麼甭管誰動了裡面的「乳酪」,另乙個變現出來的結果也會跟著變
最終結果:
昨天我們在討論設計模式的時候,遇到了乙個尖銳的問題,那就是string型別在網上說的也是一種引用型別,但是為什麼它的結果和普通的引用型別不同呢?
因為它是一種特殊的引用型別。
string與引用型別在常見的操作上有一些區別。
例如字串是不可改變的。修改其中乙個字串,就會建立乙個全新的string物件,而另乙個字串不會發生任何變化。
using system;
class stringexample
}輸出結果:
s1: aaaa
s2: aaaa
s1: bbbb
s2: aaaa
改變s1的值對s2沒有影響,這與引用型別的操作相反,當用"aaaa"初始化s1時,就在堆上分配了乙個新的string物件。在初始化s2時,引用也指向這個物件,所以s2的值也是"aaaa",但是當改變s1的值時,並不會替換原來的值,堆上會為新值分配乙個新的string物件
然後竟然還有人懷疑我,於是我畫了一張圖來解釋這個現象:
之後有夥伴認為陣列和字串都是同樣的效果,然後我們又通過乙個**來解決了一下:
static void main(string args)
;int s2 = s1;
console.writeline("s1:", s1[0], s1[1], s1[2]);
console.writeline("s2:", s2[0], s2[1], s2[2]);
s1[1] = 4;
console.writeline("s1:", s1[0], s1[1], s1[2]);
console.writeline("s2:", s2[0], s2[1], s2[2]);
console.readkey();
}最終顯示結果
s1:123
s2:123
s1:143
s2:143
顯然結果是不一樣的,所以這樣我們就可以用一般的引用型別「陣列」來襯托出特殊引用型別「string」,他們是不同的
注意:
static void strchange(string str) 是值傳遞
static void strchange(ref string str) 是引用傳遞
C 值型別,引用型別
2,引用型別 概念 值型別直接儲存其值,而引用型別儲存對其值的引用。引用型別 string,class,陣列 派生於system.array 委託 派生於system.delegate 介面。引用型別當宣告乙個類時,只在棧中分配一小片記憶體用於容納乙個位址,而此時並沒有為其分配堆上的記憶體空間。3,...
C 值型別與引用型別
1.主要內容 型別的基本概念 值型別深入 引用型別深入 值型別與引用型別的比較及應用 2.基本概念 c 中,變數是值還是引用僅取決於其資料型別。c 的基本資料型別都以平台無關的方式來定義,c 的預定義型別並沒有內置於語言中,而是內置於.net framework中。net使用通用型別系統 cts 定...
C 值型別和引用型別
c 資料型別 值型別,引用型別 概念 值型別直接儲存其值,引用型別儲存對值的引用 這兩種型別儲存在記憶體的不同地方 值型別儲存在堆疊中,引用型別儲存在託管堆上。乙個引用型別的例子,如圖 上圖中,只有乙個user物件,u1和u2都指向包含該物件的記憶體位置 執行結果 在c 中,基本資料型別如bool和...