C#中的引用類型以及特殊引用類型詳解_第1頁
C#中的引用類型以及特殊引用類型詳解_第2頁
C#中的引用類型以及特殊引用類型詳解_第3頁
C#中的引用類型以及特殊引用類型詳解_第4頁
C#中的引用類型以及特殊引用類型詳解_第5頁
已閱讀5頁,還剩4頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

第C#中的引用類型以及特殊引用類型詳解引用類型分配在哪里

引用類型變量位于線程棧。引用類型實例分配在托管堆上。當(dāng)引用類型實例的大小小于85000bytes,被分配在GC堆上,當(dāng)大于或等于85000bytes,被分配在LOH(LargeObjectHeap)上。

變量(Variable),對象(Object),實例(Instance)

變量:

變量分配在線程棧上。

變量可以是值類型,也可以是引用類型。

當(dāng)變量是引用類型時,包含了對對象的引用(內(nèi)存地址),也叫做對象引用。

對象:

對類、接口、委托和數(shù)組等的一個抽象描述。

實例:

在堆上創(chuàng)建的對象,稱為對象實例。

引用類型沒有new意味著什么?

Objecta=null;

Console.WriteLine(a.ToString());

運(yùn)行報錯未將對象引用設(shè)置到對象實例。

意思是,在線程棧上創(chuàng)建的變量a沒有指向到堆上的對象實例。

托管堆上的垃圾回收

GC會遍歷所有托管堆上的對象,按照一定的遞歸遍歷算法,對那些沒有被引用的不可訪問對象實施回收。

new的背后發(fā)生了什么

classProgram

staticvoidMain(string[]args)

Personp;

p=newPerson(20);

publicclassPerson

publicint_age;

publicPerson(intage)

_age=age;

publicPerson()

}

另外,引用類型的值,比如這里的引用類型Person中的值_age也被分配在托管堆上。

線程棧上的2個變量引用同一個對象實例的內(nèi)存地址

線程棧上的2個變量引用同一個對象實例的內(nèi)存地址,改變其中一個變量的值會影響到另外一個變量。

classProgram

staticvoidMain(string[]args)

Personp1=newPerson(20);

Personp2=p1;

Console.WriteLine("沒有改變時p2的年齡是:"+p2._age+"歲");

p1._age=18;

Console.WriteLine("改變p1的值,p2的年齡也被改變了,現(xiàn)在是:"+p2._age+"歲,真好,年輕了!");

Console.ReadKey();

publicclassPerson

publicint_age;

publicPerson(intage)

_age=age;

publicPerson()

}

string類型是特殊的引用類型

特殊性體現(xiàn)在

從應(yīng)用角度體現(xiàn)了值類型語義,從內(nèi)存角度實現(xiàn)為引用類型存儲,位于托管堆。

什么是string

可以看作是char的集合char[]

string創(chuàng)建與實例化

stringstr=Hello

以下錯誤

Stringstr=newString(Hello

因為System.String沒有提供此構(gòu)造函數(shù)

以下可以

Char[]cs={a,b,c

StringstrArr=newString(cs);

但很少使用這種方式。

字符串的恒定性Immutability

是指字符串一經(jīng)創(chuàng)建,就不可改變。

字符串一旦創(chuàng)建,在托管堆上分配一塊連續(xù)的內(nèi)存空間。

恒定性的好處:

對String對象的任意操作,不會改變原字符串。

操作字符串不會出現(xiàn)線程同步的問題。

成就了字符串駐留。

恒定性的不足:

因為恒定性,對字符串的任何操作,比如字符串比較,字符串鏈接,字符串格式化等都會創(chuàng)建新的字符串,這樣造成內(nèi)存與性能的雙重?fù)p耗。如下:

publicstaticvoidMain()

stringstr="Thisisatestaboutimmuntablilityofstringtype.";

Console.WriteLine(str.Inseert(0,"Hi").Substring(19).ToUpper());

Console.WriteLine(str);

}

由于Insert,Substring,ToUpper這些方法,都會創(chuàng)建出新的臨時字符串,而這些新的字符串不被其他代碼引用的時候,就會被垃圾回收,造成性能上的損失。

恒定性的前提,String為密封類:

publicsealedclassString:IComparable,ICloneable,IConvertible,IComparablestring,IEnumerablechar,IEnumerable,IEquatablestring

字符串駐留StringInterning

MSDN對于字符駐留的定義:公共語言運(yùn)行庫通過維護(hù)一個哈希表(HashTable)來存放字符串,該表成為拘留池,也叫駐留池。

字符串駐留彌補(bǔ)了恒定性的不足:

對于相同的字符串,CLR不會不會為其分配內(nèi)存空間,而是共享同一內(nèi)存。

CLR內(nèi)部維護(hù)了一個哈希表HashTable來管理其創(chuàng)建的大部分String對象。key是string本身,value是string對應(yīng)的內(nèi)存地址。

駐留的2個靜態(tài)方法:

publicstaticstringIntern(stringstr);

當(dāng)str位于作為key位于CLR的駐留池時,返回對str的引用,否則將str字符串添加到hashtable中,作為key,并返回引用。

publicstaticstringIsInterned(stringstr);

當(dāng)str位于作為key位于CLR的駐留池時,返回對str的引用,否則返回null引用,也不添加到hashtable中。

字符串駐留是進(jìn)程級的

可以跨應(yīng)用程序域AppDomain而存在,駐留池在CLR加載時創(chuàng)建,分配在SystemDomain中,被進(jìn)程所有AppDomain所共享,其生命周期不受GC控制。

staticvoidMain(string[]args)

stringstrA="ab";

stringstrB="ab";

Console.WriteLine(ReferenceEquals(strA,strB));

stringstrC="a";

stringstrD=strC+"b";

Console.WriteLine(ReferenceEquals(strA,strD));

strD=String.Intern(strD);

Console.WriteLine(ReferenceEquals(strA,strD));

Console.ReadKey();

}

返回:

true

false

true

分析:

strA與strB內(nèi)容相同,在hashtable中的key相同,對應(yīng)了一樣的引用地址,所以返回true。strD的內(nèi)容雖然與strA相同,但由于是動態(tài)生成的,不會把hashtable中key為ab的引用地址賦值給strD,所以strA與strD引用地址不一樣,返回false。strD=String.Intern(strD);手動對strD實施駐留,并發(fā)現(xiàn)hashtable中已經(jīng)有了ab這個key,就把對應(yīng)的引用地址賦值給了strD,這樣,strA與strD引用地址相同,返回true。

staticvoidMain(string[]args)

strings1="abc";

strings2="ab";

strings3=s2+"c";

Console.WriteLine(string.IsInterned(s3)"null");

Console.WriteLine(ReferenceEquals(s1,s3));

Console.ReadKey();

}

返回:

abc

false

分析:

string.IsInterned(s3)對s3進(jìn)行手動駐留,發(fā)現(xiàn)hashtable中abc這個key,于是,就返回abc的引用地址。但并沒有把引用地址賦值給s3。s1和s3的引用地址還是不一樣,返回false。

staticvoidMain(string[]args)

stringstrA="abcdef";

stringstrC="abc";

stringstrD=strC+"def";

Console.WriteLine(ReferenceEquals(strA,strD));

stringStrE="abc"+"def";

Console.WriteLine(ReferenceEquals(strA,StrE));

Console.ReadKey();

}

返回:

False,

true

分析:

因為strD=strC+def中strD的內(nèi)容雖然與strA想同,但因為是動態(tài)生成的,不會被添加到hashtable中,所以引用地址不一樣,返回false。abc+def在IL中呈現(xiàn)為abcdef,不是動態(tài)生成的,并且發(fā)現(xiàn)hashtable中已經(jīng)有了abcdef這個key,于是就把對應(yīng)的引用地址賦值給了strE,這樣strA和StrE就有了相同的引用地址,返回true。如圖:

staticvoidMain(string[]args)

strings="abc";

//IsInterned()獲取字符串變量的引用

Console.WriteLine(string.IsInterned(s)"null");

Console.ReadKey();

}

返回

abc。

分析:通過strings=abc使得hashtable中有abc這個key,當(dāng)進(jìn)行string.IsInterned(s)手動駐留判斷的時候,發(fā)現(xiàn)有abc這個key,就把對應(yīng)的引用地址返回。

classProgram

staticvoidMain(string[]args)

strings="ab";

s+="c";

//IsInterned()獲取字符串變量的引用

Console.WriteLine(string.IsInterned(s)"null");

Con

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論