C 變數型別 引用型別和值型別

2021-06-23 09:15:58 字數 3605 閱讀 3270

c#是一種型別安全的語言。每乙個變數都要求定義為乙個特定的型別,並且要求儲存在變數中的值只能是這種型別的值。

變數既能儲存值型別,也可以儲存引用型別,還可以是指標。這一課將講述前兩種型別,關於指標的討論我們將在下一課中進行。

下面是關於值型別和引用型別不同點的概論:

如果乙個變數v儲存的是值型別,則它直接儲存包含資料的物件。任何其他的變數v』都不能直接儲存已經由v儲存了的物件,雖然v』可以儲存乙個和v儲存的物件有著相同值的物件。(譯註:這意味著,v和v』儲存的物件毫不相干,任意改變其中乙個儲存的物件都不會影響到另乙個變數儲存的物件。)

如果變數v儲存的是乙個引用型別,它直接儲存乙個指向物件的引用,同時可能存在另乙個變數v』,它也儲存著指向這個物件的引用。(譯註:這意味著,改變v』引用的物件同時也會影響到v引用的物件,反之亦然。)

值型別在c#中你可以通過宣告列舉型別或是結構型別來定義你自己的值型別。c#以同樣的方式處理使用者自定義的型別和c#預定義的值型別,不過c#編譯器可能更優於處理後者。下面的表列出了c#中預定義的值型別的一些資訊。因為在c#中所有的基本值型別都是從object型別(最終基類)發展而來,所以下表中還顯示了與這些預定義型別相對應的.net框架中的system型別。

c# 型別

.net 框架型別

有無符號

佔據位數

取值範圍

sbyte

system.sbyte

是 1-128 到 127

short

system.int16

是 2-32768 到32767

intsystem.int32

是 4-2147483648 到 2147483647

long

system.int64

是 8-9223372036854775808 到 9223372036854775807

byte

system.byte

否 10 到 255

ushort

system.uint16

否 20 到 65535

uint

system.uint32

否 40 到 4294967295

ulong

system.uint64

否 80 到18446744073709551615

float

system.single

是 4可能值從 ±1.5 x 10-45 到 ±3.4 x 1038 ,小數點後7位有效數字

double

system.double

是 8可能值從 ±5.0 x 10-324 to ±1.7 x 10308 小數點後15到16位有效數字

decimal

system.decimal

是 12

可能值從 ±1.0 x 10-28 到±7.9 x 1028 小數點後28到29位有效數字

char

system.char

n/a2 任何16位unicode字元

bool

system.boolean

n/a1 / 2

true 或者false

在下面的**中,兩個變數都宣告為整形,並得到賦值:

int x = 10;

int y = x;

y = 20; // 這條語句執行後x的值為10,y的值為20;

引用型別

c#預定義的引用型別包括object和string型別。正如我們在上面提到的,object型別是所有其他型別的最終基類。使用者定義的引用型別可以是介面型別、類型別和委託型別(第12課會有具體介紹)。

引用型別事實上儲存乙個指向它引用的物件的記憶體位址。下面的**段中有兩個變數引用了同乙個物件(本例中,假設這個物件有乙個資料成員』myvalue』):

object x = new object();

x.myvalue = 10;

object y = x;

y.myvalue = 20; // 這條語句執行後,x.myvalue和y.myvalue的值都為20。

上面的這段**演示了引用型別的乙個特點:改變某乙個引用指向的物件的屬性同時也會影響到所有其他指向這個物件的引用。不過,strings型別雖然也是引用型別,但它的工作方式更象值型別。當乙個字串被指定了另乙個字串的值時,例如:

string s1 = "hello";

string s2 = s1;

s2和s1都引用了同乙個字串型別,但是當s1的值發生改變時,例如s1=」goodbye」;s2的值仍然是」hello」。之所以會這樣,是因為當改變s1的值是,新建立了乙個string物件,s1引用這個新的string物件;s2仍然引用原來string物件。產生這種行為的原因是string物件是恆定的,也就是說,一旦乙個string物件被建立,它的值就不能再修改,所以當改變乙個字串變數的值的時候,僅僅是新建立了乙個包含修改內容的新的string物件。

轉義序列和逐字字串(verbatim strings)

當宣告乙個字串變數時有一些字元是不能以平常的方式包含在變數中的。為了解決這個問題,c#提供了兩種不同的方法。

第一種方法是使用』轉義序列』。例如,我們想得到如下的字串

「hello world

how are you」

我們可以使用下面的語句宣告字串:string a = "\"hello world\nhow are you\""。這條語句中使用了」和換行符的轉義序列。更多字元的轉義序列可以參見下表:

character

escape sequence

' \'

" \"

\ \\

警報 \a

退格符\b 換頁符

\f 換行符

\n 回車符

\r tab 符

\t 垂直 tab 符

\v 使用數字指定的unicode 字元,如\u2000

\u 使用十六進製制數指定的unicode 字元,如\xc8

\x 空值

\0 (zero

第二種方法是使用』逐字字串』文字。這種方法將想要得到的字串放在@」和」之間。假如我們需要將c:\my documents\賦值給』path』,我們可以使用轉義序列方法:string path = "c:\\my documents\\";也可以使用如下的語句:string path = @"c:\mydocuments\"。

通過使用後一種方法得到的字串還可以橫跨多行而不需要使用』\n』。使用這種方法唯一需要使用到轉義序列的字串是」,其轉義字元為」」(兩個連在一起的雙引號)。例如想將the word "big" contains three letters.賦值給』text』,我們就可以使用如下的語句:string text = @"the word ""big"" contains three letters."。

裝箱 c#允許你將任何的值型別轉換為對應的引用型別,也可以將得到的引用型別再轉換為值型別。下面的**演示了這種轉換――裝箱:

int i = 123;

object box = i;

if (box is int)

// 這一行將會列印出來。

當第2行的**執行後,物件』box』將被初始化,i儲存的值將被複製給這個物件。值得注意的一件趣事是box執行時的型別將是被裝箱的值型別(本例中即為int)。』is』操作符將返回box的型別為int。

C 值型別和引用型別

c 資料型別 值型別,引用型別 概念 值型別直接儲存其值,引用型別儲存對值的引用 這兩種型別儲存在記憶體的不同地方 值型別儲存在堆疊中,引用型別儲存在託管堆上。乙個引用型別的例子,如圖 上圖中,只有乙個user物件,u1和u2都指向包含該物件的記憶體位置 執行結果 在c 中,基本資料型別如bool和...

c 值型別和引用型別

今天我們來學習一下什麼是值型別和引用型別。1.值型別的值存在棧上,引用型別棧上存的是位址,值在堆上 2.將乙個值型別變數賦給另乙個值型別變數時,將複製包含的值。引用型別變數的賦值只複製對物件的引用,而不複製物件本身。3.裝箱是將值型別轉換為引用型別,拆箱是將引用型別轉換為值型別,利用裝箱和拆箱功能,...

C 值型別和引用型別

型別被分為兩種 值型別 整數,bool,struct 建構函式 char 字元 小數 引用型別 string 陣列 自定義的類,內建的類,物件.兩者在記憶體中的儲存方式 值型別 只需要一段單獨的記憶體,用於儲存實際的資料,單獨定義的時候放在棧中 引用型別 需要兩段記憶體 第一段儲存實際的資料,它總是...