2

looking at this post: references updated on GC, it seems that the heap could get compacted on a Garbage collection which means that the references would change.

Now if I were to put an object in a Dictionary as a key (assume that the object does not implement GetHashCode/Equals), then the reference would be used to determine it's location within it's internal Hash table. Subsequently on a GC, if the reference changes, and I want to lookup the object how would C# find it?

tomatoRadar
  • 401
  • 3
  • 11
  • 1
    This ultimately comes does to how does the runtime generate consistent hash codes for reference types. See [this](https://stackoverflow.com/questions/1707471/how-does-object-gethashcode-work-when-the-gc-moves-an-object). The point is the hash code is not literally an address but part of the runtime's internal sync block. – Mike Zboray Apr 21 '18 at 06:49
  • Without considering the hashtable or anything, if `T` is a reference type, then any collection of items of type `T`, also including a `List`, will hold _references_ to each of its items. How it works precisely is implementation details. But surely, if the Garbage Collector decides to compact memory at some time, moving objects on the "heap" in the process, it must make sure that everyone who keeps references to these objects, including a `List<>` or a `Dictionary<,>`, gets its references updated (assuming the references are some type of memory addresses). – Jeppe Stig Nielsen Apr 21 '18 at 07:38

1 Answers1

9

The dictionary doesn't use the object's location in memory to do book-keeping - it uses the hash code. The hash code of an object doesn't change when the object is moved in memory, even if it doesn't override GetHashCode(). The details about how that works are very much implementation details, but you can definitely rely on GetHashCode() returning the same value before and after compaction (assuming the method hasn't been overridden in some bizarre and awful way).

While the implementation details can change over time, this blog post has an interesting (and recent) description. I believe that's still valid in .NET Core (as of April 2018) based on chasing code in the .NET Core CLR GitHub repo - this is a reasonable starting point, as far as I can see.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194