Reputation: 11878
I have case-insensitive HashSet<string>
:
private HashSet<string> a = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase);
I'm curious if I can now extract the string in the actual case. Pseudo code of what I need:
return a.Contains(word) ? a[word] : null;
(just a pseudo code, it won't work)
For example, I have string "TestXxX" in the HashSet. I need for the code which gets "testxxx" (or "tEsTXXx") as input and returns "TestXxX".
My current workaround is to use Dictionary<string,string>
instead and put the same value for both key and value. This is obviously not elegant and consumes 2x memory as it actually needs.
Upvotes: 6
Views: 2264
Reputation:
HashSet<T>
doesn't expose any functionality to achieve what you're looking for. If you don't need to use a HashSet
, then Kirill Polishchuk's answer makes sense to me.
Otherwise, if you do need a HashSet
, a somewhat nasty hack is to use a custom equality comparer. Create your own equality comparer that simply forwards all requests to StringComparer.InvariantCultureIgnoreCase
, but caches the last-passed objects.
If you have that, then after a.Contains(word)
returns true
, the last-passed objects should be 1) word
and 2) the word as it appears in a
.
Strictly speaking, this is not guaranteed to work, since HashSet
is allowed to call the comparer with different values than what you expect. It's certain to work in current versions of .NET Framework though and unlikely to break in the future: the comparer equality function obviously needs to be called with those arguments in order for Contains
to return the correct value, and there is no reason why it would be called with any other arguments except to intentionally break code like this.
Upvotes: 0
Reputation: 56162
You can override KeyedCollection
public class Keyed : KeyedCollection<string, string>
{
public Keyed(IEqualityComparer<string> comparer) : base(comparer)
{
}
protected override string GetKeyForItem(string item)
{
return item;
}
}
Then use it:
var keyed = new Keyed(StringComparer.InvariantCultureIgnoreCase);
keyed.Add("TestXxX");
Console.WriteLine(keyed["tEsTXXx"]);
Upvotes: 7