The designed dictionary is a WeakDictionary. That is basically a Dictionary where all values are kept through a WeakReference. The WeakDictionary does not prevent the values from being collected if they are not rooted elsewhere.
Here below is the NUnit code that I am using to test the WeakDictionary. As you can see there are lines with REQUIRED. If those lines are omitted then the last assertion fails at index itemCount - 1. Exactly like if the internal loop reference where holding a reference to the object outside there loop scope.
If I am correct (not a bug in my code), I found this behavior pretty bad and pretty counter intuitive. A reference should not continue to exist outside its scope.
Did I miss something
Joannes
Dictionary<int, object> dictionary = new Dictionary<int,object>(); WeakDictionary<int, object> weakDictionary = new WeakDictionary<int,object>(); // testing WeakDictionary.Add for (int i = 0; i < itemCount; i++) { object obj = new object(); dictionary.Add(i, obj); weakDictionary.Add(i, obj); Assert.AreEqual(dictionary.Count, weakDictionary.Count, "#A00 Unexpected Count."); obj = null; // REQUIRED BUT WHY } // testing WeakDictionary.get_Item for (int i = 0; i < itemCount; i++) { object obj1 = dictionary object obj2 = weakDictionary Assert.IsTrue(object.ReferenceEquals(obj1, obj2), "#A01 Unexpected value."); obj1 = null; // REQUIRED BUT WHY obj2 = null; // REQUIRED BUT WHY } dictionary = null; GC.Collect(); // emptying the WeakDictionary // testing the weakness of WeakDictionary for (int i = 0; i < itemCount; i++) { object obj = weakDictionary Assert.IsNull(obj, "#A02 Null value expected at index " + i + "."); } |

Bizarre GC behavior (while testing a WeakDictionary)
codepro2
I found the following that describe this effect in a bit more detail:
http://discuss.develop.com/archives/wa.exe S2=dotnet&L=DOTNET&q=&s=WeakReference%20and%20optimization&f=&a=&b=
ags2886
Hi Joannes
Are you compiling in debug mode If so, the JIT will extend the lifetimes of objects to the end of the method. Try rebuilding in release mode, and you shouldn't see the assert.
-Chris
Ushanta
If the first loop null assignement is commented-out the final assertion fails.
In the second loop, the objects are alive (because they are held into a "normal" dictionary).
Joannes
Blane Nelson
Hi taumon
I've written a blog entry about this issue:
http://blogs.msdn.com/clyon/archive/2004/12/01/273144.aspx
-Chris
JasonJ17
You could try
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
P.S. I think you should remove the null assignment in the first for loop - as it is, you assign the object in the Dictionary and WeakDictionary to null, so the assertion in the second loop just always compares null to null.
Raven.Liu
Joannes
Amol Puri
Can you post the code for the WeakDictionary