-
Type: Bug
-
Resolution: Unresolved
-
Priority: Major - P3
-
None
-
Affects Version/s: 2.11.5
-
Component/s: BSON
-
None
The GetHashCode implementation of MongoDB.Bson.Decimal128 uses the low and the high bytes to calculate a hashcode. This is problematic, because the standard allows for multiple representations of the same number. For example,
_high: 6916966077687660544, _low: 10 represents 1.0m
_high: 1, _low: 0 represents 1
This is correctly handled in the Equals implementation and `((Decimal128)1.0m).Equals((Decimal128)1)` returns `true`, however `((Decimal128)1.0m).GetHashCode().Equals(((Decimal128)1).GetHashCode())` returns `false`. The most obvious issue that this causes is that a HashSet of Decimal128 values will contain duplicates.
This is slightly affecting the Realm .NET SDK, which is in the process of adding support for a collection with Set-like semantics. When an object containing such a collection is unmanaged, it uses a HashSet to store the values. Once it gets added to the Realm database, we use a C++ implementation of the collection, which correctly detects 1.0 and 1 as duplicates and only stores one of them. From a user's perspective, it can be surprising that adding an object to the database changes the number of items in the collection.
Support for `ISet<T>` properties in Realm .NET will ship toward end of January 2021 and it would be nice, but by no means a deal breaker, to have a fix for this issue. We don't expect everyone to suddenly start using sets, and of those, only a small percentage will need to use Decimal128, so I don't imagine we'll start getting swarmed with bug reports.