2

I need to assign a guid to objects for managing state at app startup & shutdown It looks like i can store the lookup values in a dictionary using

dictionary<int,Guid>.Add(instance.GetHashCode(), myGUID());

are there any potential issues to be aware of here ?

NOTE

This does NOT need to persist between execution runs, only the guid like so

  • create the object
  • gethashcode(), associate with new or old guid
  • before app terminate, gethashcode() and lookup guid to update() or insert() into persistence engine USING GUID

    only assumption is that the gethashcode() remains consistent while the process is running

    also gethashcode() is called on the same object type (derived from window)

Update 2 - here is the bigger picture

  • create a state machine to store info about WPF user controls (later ref as UC) between runs
  • the types of user controls can change over time (added / removed)
  • in the very 1st run, there is no prior state, the user interacts with a subset of UC and modifies their state, which needs to recreated when the app restarts
  • this state snapshot is taken when the app has a normal shutdown
  • also there can be multiple instances of a UC type
  • at shutdown, each instance is assigned a guid and saved along with the type info and the state info
  • all these guids are also stored in a collection
  • at restart, for each guid, create object, store ref/guid, restore state per instance so the app looks exactly as before
  • the user may add or remove UC instances/types and otherwise interact with the system
  • at shutdown, the state is saved again
  • choices at this time are to remove / delete all prior state and insert new state info to the persistence layer (sql db)
  • with observation/analysis over time, it turns out that a lot of instances remain consistent/static and do not change - so their state need not be deleted/inserted again as the state info is now quite large and stored over a non local db
  • so only the change delta is persisted
  • to compute the delta, need to track reference lifetimes
  • currently stored as List<WeakReference> at startup
  • on shutdown, iterate through this list and actual UC present on screen, add / update / delete keys accordingly
  • send delta over to persistence

Hope the above makes it clear.

So now the question is - why not just store the HashCode (of usercontrol only) instead of WeakReference and eliminate the test for null reference while iterating thru the list

update 3 - thanks all, going to use weakreference finally

JasonMArcher
  • 14,195
  • 22
  • 56
  • 52
Kumar
  • 10,997
  • 13
  • 84
  • 134

5 Answers5

8

You appear to be assuming that a hash code will be unique. Hash codes don't work like that. See Eric Lippert's blog post on Guidelines and rules for GetHashCode for more details, but basically you should only ever make the assumptions which are guaranteed for well-behaving types - namely the if two objects have different hash codes, they're definitely unequal. If they have the same hash code, they may be equal, but may not be.

EDIT: As noted, you also shouldn't persist hash codes between execution runs. There's no guarantee they'll be stable in the face of restarts. It's not really clear exactly what you're doing, but it doesn't sound like a good idea.

EDIT: Okay, you've now noted that it won't be persistent, so that's a good start - but you still haven't dealt with the possibility of hash code collisions. Why do you want to call GetHashCode() at all? Why not just add the reference to the dictionary?

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Moreover, is there anything guaranteeing that hash codes will be stable between different runs of the same process? I know that they're not guaranteed to be stable between framework versions. – Roger Lipscombe Dec 05 '11 at 16:35
  • not adding a ref to the dict so there are no "memory leaks" i.e. i am not holding references to windows( the only type for this so no collisions) which are not on screen but my collection holds a ref and keeping it alive! now i could wrap them up in a weakreference to not hold a Gethashcode() "reference" but i can't see why it's not simpler to just use gethashcode() – Kumar Dec 05 '11 at 19:52
  • @Kumar: Why would that be a memory leak? If you don't have a reference to the existing object (and you haven't overridden GetHashCode) then you wouldn't be able to fetch the values by key later anyway. It's still entirely unclear what you're trying to achieve - if you could be *much* more precise about the bigger picture here, we're more likely to be able to help you. – Jon Skeet Dec 05 '11 at 19:58
  • It would be a mem leak as potentially the window is not on the screen/ is closed ( & the app is not ) but the ref to it in my dict would prevent it from being collected no ? will update the Q above with details on the bigger picture – Kumar Dec 05 '11 at 21:08
  • @Kumar: A weakreference is simpler than `getHashCode` because two objects might have the same hash code. – Brian Dec 05 '11 at 21:24
  • @Kumar: But my point is that if you're not going to take the hash code of the original object later, what are you going to use? You say that on shutdown you'll call GetHashCode and then look something up in the persistence engine - what what would you call it on? – Jon Skeet Dec 05 '11 at 21:34
  • @Brian - in general yes, of type Usercontrol only no – Kumar Dec 05 '11 at 21:49
  • @Jon, sorry i was not clear earlier, yes i take hashcode at the beg and also at the end, i have also detailed the scenario above, many thanks for your consideration – Kumar Dec 05 '11 at 22:08
  • @Kumar: But if you're taking the hash codes of different objects, why would you expect the hash codes to be the same? Are these your own types where you've overridden GetHashCode? – Jon Skeet Dec 05 '11 at 22:17
  • @Brian, possible but not in the same process ( or appdomain ? ) perhaps the higher powers can comment on that – Kumar Dec 07 '11 at 03:42
  • @Jon, assuming your comment was before i updated the Q but just to clarify, i expect the hashcode() for usercontrol derived types to remain static ! and no, i've not overridden them ! – Kumar Dec 07 '11 at 03:45
  • @Kumar: It's *still* not clear what you mean. Are you expecting the hash code for a particular type to be constant, without overriding? Did you read Eric's blog post, that I linked to? I think you're *fundamentally* misunderstanding what hash codes do and how they work. – Jon Skeet Dec 07 '11 at 05:07
  • @Kumar: It is legal in the same process and appdomain for two different usercontrols to have the same hashcode. You should not rely on not having collisions. The higher powers have [already commented](http://stackoverflow.com/a/8396554/18192); Eric Lippert is a principal developer at Microsoft. – Brian Dec 07 '11 at 14:09
8

Use GetHashCode to balance a hash table. That's what it's for. Do not use it for some other purpose that it was not designed for; that's very dangerous.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • that's certainly in the doc, just wondering if we can re-"use" this if possible in the *very* limited scope where it'll be used ! – Kumar Dec 07 '11 at 03:39
2

The quick and easy fix seems to be

var dict = new Dictionary<InstanceType, Guid>();
dict.Add(instance, myGUID());

Of course you need to implement InstanceType.Equals correctly if it isn't yet. (Or implement IEQuatable<InstanceType>)

sehe
  • 374,641
  • 47
  • 450
  • 633
  • This is the right way to do it. However, based on the OP's comments on Jon's answer, I think the he will want to use a [`WeakReference`](http://msdn.microsoft.com/en-us/library/system.weakreference.aspx) instead of an `InstanceType`. – Brian Dec 05 '11 at 21:21
0

Possible issues I can think of:

  • Hash code collisions could give you duplicate dictionary keys
  • Different object's hash algorithms could give you the same hash code for two functionally different objects; you wouldn't know which object you're working with
  • This implementation is prone to ambiguity (as described above); you may need to store more information about your objects than just their hash codes.

Note - Jon said this more elegantly (see above)

Community
  • 1
  • 1
Cᴏʀʏ
  • 105,112
  • 20
  • 162
  • 194
0

Since this is for WPF controls, why not just add the Guid as a dependency proptery? You seem to already be iterating through the user controls, in order to get their hash codes, so this would probably be a simpler method.

If you want to capture that a control was removed and which Guid it had, some manager object that subscribes to closing/removed events and just store the Guid and a few other details would be a good idea. Then you would also have an easier time to capture more details for analysis if you need.

Stephane Rolland
  • 38,876
  • 35
  • 121
  • 169
The Grand User
  • 727
  • 4
  • 14