WeakReference wrapping a string causes strange behavior

I know that I should only use WeakReference for large objects, but I'm wondering what the following scenario looks like:

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!

      

So far so good.

Take a look:

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?

      

what's happening?

+3


source to share


2 answers


From comments String.Intern

:

The common language framework preserves string storage by maintaining a table called a cross-domain pool, which contains a single reference to each unique literal string that is declared or created programmatically in your program. Therefore, an instance of a literal string with a specific value exists only once in the system.



So there is another link that you cannot release programmatically. Changing the code a little to generate an instance at runtime gives the expected result:

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

      

+6


source


A string is a compile-time literal, so unless you turn off automatic compile-time literal interpolation when your code is compiled (it will be enabled by default), all compile-time literal strings will be stored in a lookup table, preventing them from being GCed throughout their lifetime applications.



+5


source







All Articles