Returns a hash value for the Variant, i.e., one that will always be the same for any Variant with the same value.
For objects, it is guaranteed to be unique among all objects currently in existence (though once an object dies, a future object may use the same hash value).
Check this code:
Var lower As Variant = "garry"
Var upper As Variant = "GARRY"
Var lowerHash As Integer = lower.Hash // 67587839
Var upperHash As Integer = upper.Hash // 67587839
If lowerHash = upperHash Then
// This happens as the hashes are 67587839. They should be different.
Break
End If
I know Xojo is case-insensitive but surely the hashes for these strings should be different?
Dictionaries use hashes for their lookup functions. Because of this, string keys need to match exactly; otherwise the Dictionary will not consider them equal. The only exception to this rule is with regard to string case. The characters “a” and “A” are treated as identical in Dictionary keys because of a case-insensitive hashing function. However, non-ASCII characters such as “é” and “É” are not treated as identical in Dictionary keys, even though they are equal in a direct string comparison.
The only thing I dislike about the ParseJSON thing is it feels like a hack that is undocumented. I worry that Xojo will suddenly just change it and then my whole app collapses.
It was an unfortunate design decision that was likely a quick solution not fully thought through…
They should have either added a case sensitive dictionary subclass or added a boolean constructor (that defaulters to False) for case sensitivity on the dictionary class instead of special casing the JSON dictionary, even if it is just adding an internal delegate under the hood.
They just need to add a new constructor(CaseSensitive As Boolean = False) directly to the Dictionary Class without any subclass overhead. That can be implemented in minutes, as they already have its basis in the ParseJSON used in
ParseJSON("{}")
And the ParseJSON would use the New Dictionary(True) under hood after.
A better Constructor approach letting space for future extra options:
Class Dictionary // Just a basic set to show the proposed design
Enum Options As Integer
CaseInsensitive
CaseSensitive
End Enum
Private IsCaseSensitive_ As Boolean = False
Property IsCaseSensitive As Boolean
Get
Return IsCaseSensitive_
End Get
Set (value As Boolean)
DoWhateverItNeedsToSetAChange(value)
IsCaseSensitive_ = value
End Set
End Property
Sub Constructor(options As Dictionary.Options = Dictionary.Options.CaseInsensitive)
DoWhateverItNeedsToInit()
IsCaseSensitive = (options = Dictionary.Options.CaseSensitive)
End Sub
End Class