C# WeakReference包装字符串会导致奇怪的行为
我知道我应该只对大型对象使用WeakReference,但我对以下场景感到好奇:C# WeakReference包装字符串会导致奇怪的行为,c#,C#,我知道我应该只对大型对象使用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: fa
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?
这是怎么回事?字符串是一个编译时文本,因此除非在编译代码时关闭编译时文本的自动内联,否则默认情况下,所有编译时文本字符串都将保存在查找表中,防止在应用程序的整个生命周期内对其进行GCD。来自String.Intern的备注: 公共语言运行库通过维护一个名为intern pool的表来保存字符串存储,该表包含对程序中以编程方式声明或创建的每个唯一文本字符串的单个引用。因此,具有特定值的文本字符串的实例在系统中只存在一次 因此,还有另一个引用不能以编程方式发布。稍微更改代码以在运行时生成实例会得到预期的结果:
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
太好了,塞维!太多了!太棒了,迈克z!太多了!我在程序集信息上应用了以下属性:CompilationRelaxationsAttributeCompilationRelaxations.NoStringInterning]我的代码继续返回相同的结果。这不应该影响我们的结果吗?@ViniciusGonçalves我不熟悉这个属性,但我认为这不是一个保证,只是一个暗示。