I have a problem with HashSet
because it does not provide any method similar to TryGetValue
known from Dictionary
. And I need such method -- passing element to find in the set, and set returning element from its collection (when found).
Sidenote -- "why do you need element from the set, you already have that element?". No, I don't, equality and identity are two different things.
HashSet
is not sealed but all its fields are private, so deriving from it is pointless. I cannot use Dictionary
instead because I need SetEquals
method. I was thinking about grabbing a source for HashSet
and adding desired method, but the license is not truly open source (I can look, but I cannot distribute/modify). I could use reflection but the arrays in HashSet
are not readonly
meaning I cannot bind to those fields once per instance lifetime.
And I don't want to use full blown library for just single class.
So far I am stuck with LINQ SingleOrDefault
. So the question is how fix this -- have HashSet
with TryGetValue
?
I agree this is something which is basically missing. While it's only useful in rare cases, I think they're significant rare cases - most notable, key canonicalization.
I can only think of one suggestion at the moment, and it's truly foul.
You can specify your own IEqualityComparer<T>
when creating a HashSet<T>
- so create one which remembers the arguments to the last positive (i.e. true-returning) Equals
comparison it has performed. You can then call Contains
, and see what the equality comparer was asked to compare.
Caveats:
HashSet<T>
doesn't use any optimization such as "if the references are equal, don't bother consulting the equality comparer"I've been trying to think of other alternatives in terms of finding intersections, but I haven't got anywhere yet...
As noted in comments, it would be worth encapsulating this as far as possible - I suspect you only need a very limited set of operations, so I'd wrap a HashSet<T>
in your own class and only expose the operations you really need - that way you get to clear the "cache" after each operation, removing my first objection above.
It still feels like a horrible abuse to me, but...
As others have suggested, an alternative would be to use a Dictionary<TKey, TValue>
and implement SetEquals
yourself. That would be simple enough to do - and again, you'd want to encapsulate this in your own type. Either way, you should probably design the type itself first, and then implement it using either a HashSet<>
or a Dictionary<,>
as an implementation detail.
See more on this question at Stackoverflow