Today’s quirk was discovered while trying to get an object’s identity.
Jeffrey Richter in CLR via C# (version 2)mentions that you can call RuntimeHelpers static GetHashCode method in a box at the bottom of page 148 to get a unique ID for an object.
The documentation for the .NET framework 4 and earlier all say this about GetHashCode:
The RuntimeHelpers.GetHashCode method always calls the Object.GetHashCode method non-virtually, even if the object's type has overridden the Object.GetHashCode method. Therefore, using RuntimeHelpers.GetHashCode differs from calling GetHashCode directly on the object with the Object.GetHashCode method.
But, if you change to the Silverlight version of the documentation of GetHashCode that statement is missing, and if you actually build the code you’ll find that it just calls GetHashCode on the object itself, with whatever override is provided on that type (as these people found out)
Further investigation into GetHashCode all the way back to V2 of the framework looks unpromising as well:
The default implementation of the GetHashCode method does not guarantee unique return values for different objects. Furthermore, the .NET Framework does not guarantee the default implementation of the GetHashCode method, and the value it returns will be the same between different versions of the .NET Framework. Consequently, the default implementation of this method must not be used as a unique object identifier for hashing purposes.
There is some information here on other possible strategies on stackoverflow for getting an identity.
My intended use was for serialization, and the above thread points out the ObjectIDGenerator class which looks like exactly the functionality I’m looking for, but it doesn’t work on Silverlight!
GCHandle also doesn’t look like it will do the job, as most members are security critical, and the only value it gives out is a pinned address anyway, though there is a promising Narrowing operator, so casting to an IntPtr looks like it might work.
However, when I try to run it I get an exception:
Attempt to access the method failed: System.Runtime.InteropServices.GCHandle.set_Target(System.Object)
which I guess is expected as they’re marked with [SecurityCritical] attributes.
Despite all that, it does appear that object.ReferenceEquals will tell me if two objects are the same, and a promising approach appears to be
Dictionary<object, int> dict = new Dictionary<object, int>(10);
var datesTmp = new EphemeralState();
Dictionary<object, int> dict =
new Dictionary<object, int>
(10, ObjectReferenceEqualityComparerer<object>.Default);
dict[datesTmp] = 1;
var datesTmp2 = new EphemeralState();
dict[datesTmp2] = 2;
Debug.WriteLine(dict.Count);
No comments:
Post a Comment