-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[API Proposal]: Add OrderedSet<T>
#110882
Comments
Tagging subscribers to this area: @dotnet/area-system-collections |
Why does this need to be in the BCL and not as a third party nuget package? |
This can mostly be implemented with an |
I am one of those that had to write my own implementation, based on an old version of Dictionary<K,V> OrderedSet is essentially a Hash when writing, but a List when reading, and its a kind of collection that is very relevant in computer graphics. The common usage of such a collection is when you need a hash where you want to ensure every added item is unique,, but you also need to keep track of the insertion order and reference the added items by index. A naive implementation that explains the use case would look like this: Dictionary<TValue,int> _HashedIndices;
List<TValue> _Values;
int GetOrAdd(TValue val)
{
if (_HashedIndices.TryGetValue(val, out var index) return index;
index = _Values.Count;
_HashedIndices[val] = index;
_Values.Add(val);
return index;
} Notice this is a naive implementation that has the problem of consuming twice the memory an OrderedSet would consume, specially if TValue is a large struct (which is fairly common when using this pattern) Btw, if OrderedSet naming is not liked, I usually go for IndexableSet. |
Could you elaborate on the implementation? |
My implementation is a modification of Actually, my implementation goes a bit further and removes the "key" of the dictionary altogether, so it saves a lot of memory. That way you get the behaviour I exposed in the naive example, but with a single collection and less memory footprint. This is important because in computer graphics it is not uncommon to deal with millions of items. |
But how do you guarantee that the elements are unique, if they are values in the dictionary? And how you get the index of an existing item? |
Because under the hood, Dictionary<TKey,TValue> is a list with extra sugar to handle access by key.... but if you remove the extra sugar for the key thing, you can simplify the whole code so the "key" is an index. Here's my implementation (don't mind the naming): https://github.com/vpenades/SharpGLTF/blob/master/src/SharpGLTF.Toolkit/Collections/ValueListSet.cs |
Sorry, if I miss something, I have not had the chance to run the code yet, but it looks to me that it heavily relies on the fact that there is no removals and thus there could not be a scenario when an element at index 9999 is in a collection with 1 element (scenario: 9999 elements added, each one except the last removed after the addition) , which seems possible to achive with your naive implementation above, and is probably not what issue's creator proposes: the proposed API includes The same as with the original author's API, why do you suppose it should be included in BCL and not provided by a NuGet for specialized tasks? |
Background and motivation
Bringing this issue back since it was closed without being resolved. (#24828 and dotnet/corefxlab#2457):
"Sometimes I've come across places when needing a HashSet where the insertion order of the elements is important to me. Unfortunately, .NET does not have an OrderedSet class even though it has a SortedSet which to me has less value but perhaps not to others. This has led to users rolling their own solution, typically by using a combination of a LinkedList and Dictionary field resulting in the worst of both worlds in terms of performance and resulting in larger memory usage, and even worse sometimes users instead rely on implementation details of HashSet for ordering which is quite dangerous."
API Proposal
API Usage
Alternative Designs
No response
Risks
No response
The text was updated successfully, but these errors were encountered: