Hashtable with sorting & non case-sensitive key searches

headkaze

Newcomer
Joined
Sep 5, 2006
Messages
23
A Hashtable is perfect for storing a section of an ini file in memory because it has the key/value combination like an ini file. So I wish to use a Hash table but there are two features of a Hashtable I don't like.

1. ht["name"] is not the same as ht["Name"] (ie. Case sensitive). For an ini file this is bad because ini files don't need case sensitive text to work. In this case I can't have this case sensitive.

2. Enumerating a hash table wont return the items in the order they were added:

Eg.
Code:
IDictionaryEnumerator en =  ht.GetEnumerator();

while (en.MoveNext())
{
	MessageBox.Show(en.Key + "=" + en.Value);
}

While it's not important that I have the items enumerated in the order I add them it would be preferable because creating a new ini file would allow me to write to it in the same order I read them.

Is there something like a Hashtable that will allow me to have the two features above? Thanks in advance for any help.
 
In terms of the case sensitivity it might be easiest to create a class that inherits from Hashtable and override the relevant Methods (Add, Remover, etc.) and simply upper or lower case the string used as a key value to prevent case being an issue.

The order of returned elements is a more fundamental issue and relates to the internal storage mechanism use by hashtables - solving this wouldn't be trivial. If this is a real problem you might want to look at creating your own custom collection class.
 
This is what I was afraid of. It annoys me there is no built in collection class that has the two features I need. I think I'll need to use inheritence on the HashTable class and add some extra methods, or override like you said.

Oh well, thanks for the reply.
 
Which version of C# are you using? If you are using version 2.0 then there is a very easy (and more type safe) solution for problem #1.

You can use the generic dictionary class and create your own IEqualityComparer<String> class that compares strings with case insensitivity.

C#:
// Class that compares two strings in a case-insensitive manner.
class InsensitiveComparer:IEqualityComparer<string>
{
    public bool Equals(string x, string y) {
        // To do the comparison we use a string.Equals overload that allows us to ignore case
        return string.Equals(x, y, StringComparison.InvariantCultureIgnoreCase);
    }

    // This method exists only because it is required for the interface.
    public int GetHashCode(string obj) {
        return obj.ToUpper().GetHashCode();
    }

}

// This is a string-key and string-value dictionary that uses case-insensitive keys.
class NiftyStringDictionarty : Dictionary<string, string>
{
    public NiftyStringDictionarty() : base(new InsensitiveComparer()) { }
}
This, of course, doesn't really help with problem #2.
 
You don't need 2.0 to get a simple case insensitive hashtable, System.Collection.Specialized.CollectionUtils.CreateCaseInsensitiveHashtable() does exactly that for you and has been present since 1.0. If you are using 2.0 and you want a case insensitive string comparer it makes sense to use System.StringComparer.InvariantCultureIgnoreCase or System.StringComparer.CurrentCultureIgnoreCase rather than going to the trouble of writing your own.

If you want an IDictionary with ordered why not look at the OrderedDictionary class that was added in 2.0? its in System.Collection.Specialized. It has a constructor which takes only an IEqualityComparer as an argument and helpfully StringComparer (and all its various static fields since they are derived from StringComparer) all implement IEqualityComparer and IEqualityComparer<string>. That means all you have to do is import System and System.Collections.Specialized and you can have a class that does exactly what you want with:
Code:
IDictionary variable = new OrderedDictionary(StringComparer.CurrentCultureIgnoreCase);
 
Wraith said:
If you are using 2.0 and you want a case insensitive string comparer it makes sense to use System.StringComparer.InvariantCultureIgnoreCase or System.StringComparer.CurrentCultureIgnoreCase rather than going to the trouble of writing your own.

I suppose it would be easier to spend thirty seconds exploring the object browser instead of thirty-five writing seven or so lines of code. You win this time...
 
Back
Top