3

I know that i should use WeakReference just for large objects, but I am curious about the following scenario:

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 it's alright.

Look this:

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 going on?

Vinicius Gonçalves
  • 2,514
  • 1
  • 29
  • 54

2 Answers2

6

From the remarks of String.Intern:

The common language runtime conserves string storage by maintaining a table, called the intern pool, that contains a single reference to each unique literal string declared or created programmatically in your program. Consequently, an instance of a literal string with a particular value only exists once in the system.

Thus there is another reference that you can't release programmatically. Changing your code slightly to generate an instance at run time 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
Mike Zboray
  • 39,828
  • 3
  • 90
  • 122
  • awesome, mike z! tks a lot! – Vinicius Gonçalves May 06 '15 at 17:39
  • I applied the following attribute on my assembly info: CompilationRelaxationsAttribute(CompilationRelaxations.NoStringInterning)] My code continues returning the same result. This should not affect our results? – Vinicius Gonçalves May 06 '15 at 18:11
  • 1
    @ViniciusGonçalves I am not familiar with that attribute, but [other](http://stackoverflow.com/questions/15778165/compilationrelaxations-attribute-not-working) [questions](http://stackoverflow.com/questions/15601916/how-does-compilationrelaxations-nostringinterning-actually-work) suggest that it is not a guarantee, simply a hint. – Mike Zboray May 06 '15 at 18:18
5

The string is a compile time literal, so unless you turn off automatic interning of compile time literals when compiling your code (it'll be on by default) all compile time literal strings will be held in a lookup table, preventing them from being GCed throughout the lifetime of the application.

Servy
  • 202,030
  • 26
  • 332
  • 449