C 菜鳥之旅 值型別,引用型別

2021-09-09 09:20:25 字數 3245 閱讀 6389

所以針對值型別和引用型別這個問題,我展開了一系列的學習。下面是我的一些收穫,分享給大家。

在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和...