由于在.net中存在兩種類型,分別是值類型(value type)和引用類型(reference type),所以很多關(guān)于c#中參數(shù)傳遞的混淆就因此而生。
首先要弄清楚的是:值類型是分配在棧(stack)上面,而引用類型分配在堆(heap)上面。棧是一種先進(jìn)后出,并且由系統(tǒng)自動操作的存儲空間。而堆(在.net上準(zhǔn)確的說是托管堆 managed heap)是一種自由儲存區(qū)(free memory),在該區(qū)域中,必須明確的為對象申請存儲空間(一般在java和c#中都是使用的new關(guān)鍵字),并可以在使用完以后釋放申請的存儲空間(java和c#都使用垃圾回收機(jī)制 garbage collector自動釋放對象空間)
引用類型(reference type):它存放的值是指向數(shù)據(jù)的引用(reference),而不是數(shù)據(jù)本身。示例:
system.text.stringbuilder sb = new stringbuilder();
這里,我們聲明一個變量sb,并通過new stringbuilder()創(chuàng)建了一個stringbuilder(與java中stringbuffer類似)對象,再將對象的引用(reference)賦值給變量sb,即變量sb中保存的是stringbuilder對象的引用,而非對象本身。
system.text.stringbuilder first = new stringbuilder();
system.text.stringbuilder second = first;
這里,我們將變量first的值(對一個stringbuilder對象的引用)賦值給變量second,即first和second都指向同一個stringbuilder對象。對stringbuilder對象的任何修改都會影響到first和second變量。
system.text.stringbuilder first = new stringbuilder();
system.text.stringbuilder second = first;
first.append("hello");
first = null;
console.writeline(second);
這里,輸出的結(jié)果是 hello。由于first和second都含有對同一stringbuilder對象的引用。然后通過first的引用調(diào)用stringbuilder對象的append方法,將對象進(jìn)行修改,即添加字符串“hello”,然后又將first賦值為null,表示讓first不引用任何對象。最后通過second的引用隱式調(diào)用stringbuilder對象的tostring方法輸出“hello”。由此可見,first的值改變了(被賦值為null),而它所引用的對象并不會發(fā)生改變,second照樣引用到stringbuilder對象。
class類型,interface類型,delegate類型和array類型都是引用類型。
值類型(value type):引用類型中變量和實(shí)際數(shù)據(jù)之間還隔了一間接層,而值類型就完全不存在,值類型的變量直接保存的就是數(shù)據(jù)。
struct intholder
{
public int i;
}
這里,結(jié)構(gòu)是值類型,intholder是一個結(jié)構(gòu):
intholder first = new intholder();
first.i = 5;
intholder second = first;
first.i = 6;
console.writeline(second.i);
輸出結(jié)果為5。這里second = first 以后second保存的是first的值拷貝,即second.i = 5;而后來的first.i發(fā)生了改變并不會影響second.i。所以輸出值為5。
簡單類型(比如int,double,char),enum類型,struct類型都是值類型。
注意:有一些類型(比如string類型)的行為看起來像值類型,但實(shí)際上是引用類型。這些類型被稱為immutable類型,也就是說這種類型的實(shí)例只要被構(gòu)造好就不會改變。比如,string.replace()并不會改變調(diào)用它的字符串對象,而是返回含有新數(shù)據(jù)的新的字符串對象。
新聞熱點(diǎn)
疑難解答
圖片精選