Brian Campbell
Brian Campbell

Reputation: 171

Ignore case in Dictionary ContainsKey Where key is dynamic

I have a Dictionary<dynamic, string> and when checking if the dictionary contains a key, if the key is a string I would like to ignore the case. Is this possible?

Upvotes: 1

Views: 10339

Answers (2)

Darren H
Darren H

Reputation: 460

You could add an extension to the Dictionary which determines if the key is of type string, and if so, uses case insensitive comparison; otherwise, it uses the default comparison.

public static class DictionaryExtension
{
    public static bool ContainsKeyIgnoreCase<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key)
    {
        bool? keyExists;

        var keyString = key as string;
        if (keyString != null)
        {
            // Key is a string.
            // Using string.Equals to perform case insensitive comparison of the dictionary key.
            keyExists =
                dictionary.Keys.OfType<string>()
                .Any(k => string.Equals(k, keyString, StringComparison.InvariantCultureIgnoreCase));
        }
        else
        {
            // Key is any other type, use default comparison.
            keyExists = dictionary.ContainsKey(key);
        }

        return keyExists ?? false;
    }
}

You can then use it like this:

var foo = new Foo();
var dictionary =
    new Dictionary<dynamic, string>
    {
        { 1, "One" },     // key is numeric
        { "Two", "Two" }, // key is string
        { foo, "Foo" }    // key is object
    };

dictionary.ContainsKeyIgnoreCase("two");     // Returns true
dictionary.ContainsKeyIgnoreCase("TwO");     // Returns true
dictionary.ContainsKeyIgnoreCase("aBc");     // Returns false
dictionary.ContainsKeyIgnoreCase(1);         // Returns true
dictionary.ContainsKeyIgnoreCase(2);         // Returns false
dictionary.ContainsKeyIgnoreCase(foo);       // Returns true
dictionary.ContainsKeyIgnoreCase(new Foo()); // Returns false

Note:
The extension example above is using StringComparer.InvariantCultureIgnoreCase. You may need to modify the comparison for your needs.

Upvotes: 3

user6842156
user6842156

Reputation:

There's no reasonable way you could implement a case-insensitive get on a case-sensitive hash map.

Although you can create a new case-insensitive dictionary with the contents of an existing case-sensitive dictionary (if you're sure there are no case collisions):-

var oldDictionary = ...;
var comparer = StringComparer.OrdinalIgnoreCase;
var newDictionary = new Dictionary<string, int>(oldDictionary, comparer);

Let me know, if it works.

Upvotes: 2

Related Questions