C#變數型別(1):引用型別和值型別 (轉)

amyz發表於2007-11-28
C#變數型別(1):引用型別和值型別 (轉)[@more@] 

C#是一種型別的語言。每一個變數都要求定義為一個特定的型別,並且要求在變數中的值只能是這種型別的值。:namespace prefix = o ns = "urn:schemas--com::office" />

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

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

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

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

值型別

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

型別

.Net 框架型別

有無符號

佔據位數

取值範圍

sbyte

System.Sbyte

1

-128 到 127

short

System.Int16

2

-32768 到32767

int

System.Int32

4

-2147483648 到 2147483647

long

System.Int64

8

-9223372036854775808 到 9223372036854775807

byte

System.Byte

1

0 到 255

ushort

System.Uint16

2

0 到 65535

uint

System.UInt32

4

0 到 4294967295

ulong

System.Uint64

8

0 到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/A

2

任何16位Unicode字元

bool

System.Boolean

N/A

1 / 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=”gooye”;s2的值仍然是”hello”。之所以會這樣,是因為當改變s1的值是,新建立了一個string物件,s1引用這個新的string物件;s2仍然引用原來string物件。產生這種行為的原因是string物件是恆定的,也就是說,一旦一個string物件被建立,它的值就不能再修改,所以當改變一個字串變數的值的時候,僅僅是新建立了一個包含修改內容的新的string物件。

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

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

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

  “Hello World

  How are you”

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

 

Character

Escape Sequence

'

'

"

"

警報

a

退格符

b

換頁符

f

換行符

n

回車符

r

Tab 符

t

垂直 Tab 符

v

使用數字指定的Unicode 字元,如u2000

u

使用十六進位制數指定的Unicode 字元,如xc8

x

空值

(zero

  第二種方法是使用’逐字字串’文字。這種方法將想要得到的字串放在@”和”之間。假如我們需要將C:My Documents賦值給’path’,我們可以使用轉義序列方法:string path = "C:My Documents";也可以使用如下的語句:string path = @"C:MyDocuments"。

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

  裝箱

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

int i = 123;
object box = i;
if (box is int)
{Console.Write("Box contains an int");} // 這一行將會列印出來。

  當第2行的程式碼執行後,物件’box’將被初始化,i儲存的值將被複制給這個物件。值得注意的一件趣事是box執行時的型別將是被裝箱的值型別(本例中即為int)。’is’運算子將返回box的型別為int。 


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752019/viewspace-985650/,如需轉載,請註明出處,否則將追究法律責任。

相關文章