Search code examples
c#sortingsortedset

C# SortedSet<T> uses the custom comparer for add/remove/contains as well as sorting?


I was trying to use a SortedSet to keep a set of objects in order with a custom comparer but found that SortedSet is not working how I expected or how the documentation describes it. When using Add(), Remove(), or Contains() the SortedSet uses the custom comparer to find the target item in the list instead of checking the items themselves.

For example if I have a SortedSet of vectors and have the custom comparer compare them by their magnitudes if I first add a vector (1, 2) and then try to add (2, 1) it will fail because the comparer says they are equal.

Is this how it should work? The documentation only says that the comparer is used for sorting and that Add() doesn't allow duplicate elements, I feel it could really use a note about the custom comparer if that is intended.

Additionally: Is there a sorted collection that does what I am looking for? A Key/Value pair collection that sorts on the value so there may be duplicate values.


Solution

  • Is this how it should work?

    Yes, if the comparer returns 0 it means the items are equal, and since it is a set, it will not allow multiple items that are equal.

    Is there a sorted collection that does what I am looking for? A Key/Value pair collection that sorts on the value so there may be duplicate values.

    That depend on what you are looking for and what you goal is. It is probably a good idea to list the operations that need to be supported, and what algorithmic complexity you need for each one. As a rule of thumb, key value collections would use the key as the index. The built in collections are intended for common usages. If you have some specialized use case you may need to create your own collection type.

    There is a MultiValueDictionary that allow multiple values for a single key. Unfortunately it seem the package has been deprecated, but it is not that difficult to create your own equivalent collection.

    There is a sorted dictionary, that could be extended to allow for multiple values per key. Just use a backing SortedDictionary<double,List<TValue>>, with an add method that either creates a new list or adds the value to the existing list.

    If you want have spatial data you would typically use some kind of tree. R-Tree is the typical spatial index. But Kd-Tree or Quad-tree are also alternatives. There are no built in types for this in c#, but some databases have spatial indices, and there should be plenty of third party libraries if you look around.