Few days ago I was trying to put some Guids into the ItemCollection of a fresh, new WorkItem - I used that pattern earlier and never noticed anything strange going on. But this time was a totally different... What I did was something like this:
Guid a = Guid.Empty;
Guid b = Guid.Empty;
WorkItem.Items.Add(a, "A");
WorkItem.Items.Add(b, "B");
so since this point of development I didn't had the needed Values so I filled empty guids to test other stuff before implementing this. So at another point I tried to get the values out of the collection by its keys "A" and "B" (well I had real names for it but lets keep it simple)
Guid a = (Guid)WorkItem.Items["A"];
Guid b = (Guid)WorkItem.Items["B"];
unfortunally this threw an exception sometimes because null was returned... Yes - sometimes - not always... Nice... As I took a closer look it turned out that only the second line might crash and that the chance that this happens was growing with the elapsed time since I put the Guids in... so at this point it seemed a bit like radioactive decay... ok you'll guess that it was not only time - so I could speed up the decay by doing some operations in my window... I suspected it had something to do with the garbage collection since it is done asynchronously and may occur more often the more operations allocate memory. Besides there is no way to put any null in the WorkItem.Items-Collection which means that no other side effect should be abled to have Item B modified.
I played a bit around and found out, that always the last inserted item might disappear while the other one was stable. I also figured out that different values made both items stable so I asked myself if there might be any selfcleaning process in the CAB that would remove duplicates sometimes but what would that make sense for since the items where added with an explicit ID ("A" & "B").
Ok the solve of the mystery was quite a bit of both... so a little session with the .NET Reflector later I think I found what explained this. It turned out that even when an explicit ID was given the collection was searched for an
Equal value. If it found one it did not add the Item to the list instead it used a method called BuildRepeatedItem and this -some levels deeper- (through the ReadWriteLocator...) led into not adding it to any list but into a Dictionary<TKey, WeakReference> and like its written on a Microsoft page:
"WeakReference Class - Represents a weak reference, which references an object while still
allowing that object to be reclaimed by garbage collection."
nice... so whats the error here anyway? I don't currently see why a WeakReference should be applied to something that comes from the "API-User" and could be anything. On the other hand it does also not make much sense to compare the values if an ID is given. Ok maybe it was never intended to add simple value types into the workItem.Items-Collection but I think the problem would never occur if the Contains-Check in the Collection would have been done in a ReferenceEqual-comparison way instead of an Equality-comparison which leads to different results with value and reference types.