值型別和引用型別

2021-04-20 01:03:46 字數 2789 閱讀 9957

為了更好地說明兩種型別之間的區別,借用如下的**來說明:

值型別引用型別

記憶體分配地點

分配在棧中

分配在堆中

效率效率高,不需要位址轉換

效率低,需要進行位址轉換

記憶體**

使用完後,立即**

使用完後,不是立即**,等待gc**

賦值操作

進行複製,建立乙個同值新物件

只是對原有物件的引用

函式引數與返回值

是物件的複製

是原有物件的引用,並不產生新的物件

型別擴充套件

不易擴充套件

容易擴充套件,方便與型別擴充套件

通過如上細緻對比,大家對於值型別和引用型別有個清楚的概念。

不過,無論是對於值型別還是引用型別來說,對於其作為函式引數或者返回值的時候,都是容易犯錯誤的地方。

對於值型別來說,當其作為函式引數的時候,希望在函式中被修改,那麼直接如下操作是不能被修改的:

c#** 

public

void

increment( 

int

i )     

view plain

copy to clipboard

print?

public

void

increment( 

inti )  

要想在函式中對傳進去的引數做真正的修改,需要借助於ref這個關鍵字,那麼正確的形式如下:

c#** 

public

void

increment( 

ref

int

i )     

view plain

copy to clipboard

print?

public

void

increment( 

refint

i )  

也就是說,如果需要在函式中對值型別引數進行修改,需要用ref或者out進行標識才能真正實現。

而對於引用型別來說,當其作為函式引數的時候,它所遇到的情況恰恰與值型別相反,即不希望在函式中被修改,舉例如下:

c#** 

public

void

addvalue( mytype typvalue )     

view plain

copy to clipboard

print?

public

void

addvalue( mytype typvalue )  

由於對於引用型別物件來說,其的賦值操作只是對原有物件的引用,因此在函式對其修改,實際上是直接修改了原有物件資料,這是很多情況不希望發生的(這裡例如對陣列或者datatable操作這類)。

為了防止這種事發生,需要給此型別提供clone函式。例如對於如上的型別,可以入下實現 :

c#** 

public

class

mytype:icloneable   

get

}   

public

mytype()   

{}   

public

mytype( 

int

value)   

#region icloneable members   

public

object

clone()   

#endregion   

}  

view plain

copy to clipboard

print?

public

class

mytype:icloneable  

get}  

public

mytype()  

{}  

public

mytype( 

intvalue)  

#region icloneable members  

public

object

clone()  

#endregion  

}  那麼在呼叫的時候,用當前的物件的clone作為引數即可。

不過對於引用型別來說,提供乙個clone函式不是一件容易的事情,尤其出現引用型別巢狀的時候,所以說去實現乙個完全clone功能是件很費事又不討好的活,這也就是在論壇中常說的深copy和淺copy的問題。話雖如此,如果對於前面所說的有個大概了解,相信實現也不是不可能。

在c#中,尤其自己定義型別的時候,常常由於是用struct來定義還是用class來定義,即是定義乙個值型別還是乙個引用型別呢。在這本書上給了幾個判定條件,如果如下幾點都滿足的話,建議用struct來定義為值型別,否則用class定義為引用型別。

1. 這個型別是否主要為了資料儲存;

2. 是否只通過屬性來訪問物件的資料成員;

3. 這個型別是否不會有子型別;

4. 在程式處理的時候不會把這個型別物件通過多型來處理。

引用型別和值型別

c 是一種型別安全的語言。每乙個變數都要求定義為乙個特定的型別,並且要求儲存在變數中的值只能是這種型別的值。變數既能儲存值型別,也可以儲存引用型別,還可以是指標。這一課將講述前兩種型別,關於指標的討論我們將在下一課中進行。下面是關於值型別和引用型別不同點的概論 如果乙個變數v儲存的是值型別,則它直接...

引用型別和值型別

c 中值型別和引用型別作為方法引數傳遞的時候其實都可以說是 值 的傳遞,只不過這裡的 值 指代的東西有所區別。當方法的引數為值型別時,方法傳遞的是值本身的值。當方法的引數為引用型別時,方法傳遞的則是應用型別的引用的位址,也就是引用型別位址在棧上的值。舉個引用型別作為引數傳遞的例子 static vo...

值型別和引用型別

變數 常量和杖舉 常量 用來代替乙個數或字串的名稱,我們可以在初始化時定義。在變數前增加關鍵字 const 就可以把這個變數設定為常量。語法如下 訪問修飾符 const 資料型別 常量名 值 注 常量在使用過程中是不能被修改的,如果要修改乙個常量的話程式會發生錯誤。杖舉 事先考慮到某一變數可能取得值...