IEquatable<T> Is A Bad Idea On Unsealed Types
airbreather opened this issue · comments
IEquatable<T>
exists for basically one purpose only: to avoid the performance-related overhead of casting + boxing/unboxing overhead of object
when an instance of the type is stored in a hash-based collection. Without the concern of performance, bool Equals(object)
would be sufficient. So if type Foo
is expected to be used as the key in a hash-based collection, especially if it's a value type, it is sometimes recommended that Foo
should implement IEquatable<Foo>
.
I've never seen a use case where it is useful for an interface type IFoo
to implement IEquatable<IFoo>
, and every time I have seen this at work, it has been a mistake. Same goes for the NTS projects, it seems.
I'm pretty sure this actually makes GeoAPI's GeoAPI.Geometries.IGeometry
differ semantically from JTS's org.locationtech.jts.geom.Geometry
, because the latter just uses the Java equivalent to .NET's bool Equals(object obj)
, which uses boolean equalsExact(Geometry other)
, for all Java collections:
new Dictionary<ILineString, string>()
will usebool Equals(object obj)
to compare keys.new Dictionary<Geometry, string>()
will usebool Equals(object obj)
to compare keys.new Dictionary<IGeometry, string>()
will usebool Equals(IGeometry other)
to compare keys.
It's possible to "fix" IEquatable<T>
and keep it around by taking some breaking changes, but the result would be expensive to implementers and confusing to maintainers and consumers alike. I think we should consider a breaking change to drop every IEquatable<T>
from this repository, with one exception: Interval is actually recommended to implement this interface, because it's a struct type.
After, we should consider whether or not to add bool Equals(IGeometry geometry)
itself to IGeometry
.
- I personally think we shouldn't have that on
IGeometry
because it already has bothbool EqualsExact(IGeometry other)
andbool EqualsTopologically(IGeometry other)
. - JTS javadoc mentions that its
boolean equals(Geometry g)
is only there "for backward compatibility reasons" now thatequalsTopo
exists. - This is tricky to do, ourselves, in such a way that the result is both backwards-compatible and faithful to JTS. Perhaps what we should do is keep
bool Equals(IGeometry other)
around, but mark it with[Obsolete(..., error: true)]
to force consumers to explicitly sayEqualsTopologically
if that's what they want.
I have similar thoughts about IComparable<T>
, but that's a trickier subject because we inherited some of that messiness from JTS, so I'm not sure what I want to propose that we do about that one yet. It'll be a separate issue, if anything.
I support the removal of IEquatable<IGeometry>
, even though it has been there from the very beginning.
IComparable<IGeometry>
deserves a seperate issue.
Note: the concerns here may intersect somewhat with locationtech/jts#159.