It doesn't return a value based on the address. It returns a value based on the sync block for the object.
The sync block is allocated the first time object.GetHashCode
is called (when not overridden) or there's contention on the lock for the object. (It may be allocated if you call Wait/Pulse/PulseAll too, I haven't looked.)
The sync block is independent of the location of the object's main data in memory. Basically (as I understand it) there's one big table for sync blocks - which is kept efficient in some fashion, partly due to not every object requiring one (only ones where the system hashcode is required, or locking).
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…