2015-05-06 81 views
3

我知道,我應該使用WeakReference的只是大的物體,但我很好奇以下情形:WeakReference的包裝字符串引起奇怪的行爲

object obj = 1; //Int32 

var wk = new WeakReference(obj); 

Console.WriteLine(wk.IsAlive); //Prints: True 

obj = null; 

GC.Collect(2, GCCollectionMode.Forced, true); 

Console.WriteLine(wk.IsAlive); //Prints: false, All Rigth! 

到目前爲止,這是正常的。

看看這個:

object obj = "test"; //String 

var wk = new WeakReference(obj); 

Console.WriteLine(wk.IsAlive); //Prints: True 

obj = null; 

GC.Collect(2, GCCollectionMode.Forced, true); 

Console.WriteLine(wk.IsAlive); //Prints: True, Why? 

這是怎麼回事?

回答

6

String.Intern的言論:

公共語言運行庫通過維護表節省字符串存儲,叫實習生池,包含一個單一的參考聲明或程序中的程序創建的每一個獨特的文本字符串。因此,具有特定值的文字串的實例僅在系統中存在一次。

因此,有另一個引用,您不能以編程方式發佈。稍微更改您的代碼以在運行時生成實例,可獲得預期的結果:

object obj = new string(new char[] { 't', 'e', 's', 't' }); 
var wk = new WeakReference(obj); 
Console.WriteLine(wk.IsAlive); //Prints: True 
obj = null; 
GC.Collect(2, GCCollectionMode.Forced, true); 
Console.WriteLine(wk.IsAlive); //Prints: False 
+0

真棒,邁克z!很多! –

+0

我在我的程序集信息中應用了以下屬性: CompilationRelaxationsAttribute(CompilationRelaxations.NoStringInterning)] 我的代碼繼續返回相同的結果。 這應該不會影響我們的結果嗎? –

+1

@ViniciusGonçalves我不熟悉該屬性,但[其他](http://stackoverflow.com/questions/15778165/compilationrelaxations-attribute-not-working)[問題](http://stackoverflow.com/questions/ 15601916/how-does-compilationrelaxations-nostringinterning-actually-work)暗示它不是保證,只是一個提示。 –

5

該字符串是一個編譯時間字面量,因此除非在編譯代碼時關閉編譯時文字的自動實習(它將在默認情況下啓用),所有編譯時間文字字符串將保存在查找表中,從而防止他們從整個應用程序的整個生命週期中獲得GC。

+0

完美,Servy!需要很多! –