LP on .NET

December 27, 2011

Case-Invariant Dictionaries

Filed under: .NET,C# — Larry Parker @ 4:26 pm

A few months back I posted about case-invariant string comparisons using the Equals method and the StringComparison enum.  This approach made it a bit more efficient to compare strings without regards to their case since it wasn’t necessary to convert the strings to lower or upper case.

But what if you have a dictionary that is keyed by a string and you wish the lookup to be case insensitive?  The following unit test demonstrates the problem, using a dictionary of city names and temperatures:

private Dictionary<String, Int32> GetDictionary()
{
    Dictionary<String, Int32> dict = new Dictionary<String, Int32>()
    {
        {"New York", 42},
        {"Boston", 35},
        {"Atlanta", 58}
    };
    return dict;
}

[TestMethod]
public void CaseInsensitive_KeyNotFound_Test()
{
    Dictionary<String, Int32> dict = GetDictionary();

    Assert.IsFalse(dict.ContainsKey("new york"));
}

As the test shows, searching the dictionary for the lower-case city of “new york” fails.  If you ask the user to input a city name and they don’t enter it as mixed case, you’re out of luck.

A workaround is to store the cities in the dictionary as upper (or lower) case and always ensure you search by the same case.  But that gets a bit messy.

Fortunately there’s a better way.  One of the Dictionary<TKey, TValue> constructors takes an IEqualityComparer<TKey> that lets you specify how you would like to compare the key of the dictionary.

The following unit test demonstrates this:

[TestMethod]
public void CaseInsensitive_KeyFound_Test()
{
    Dictionary<String, Int32> dict = new Dictionary<String, Int32>(StringComparer.OrdinalIgnoreCase)
    {
        {"New York", 42},
        {"Boston", 35},
        {"Atlanta", 58}
    };

    Assert.IsTrue(dict.ContainsKey("new york"));
}

In this example, we pass in a StringComparer.OrdinalIgnoreCase parameter that tells the dictionary to perform a case-insensitive string comparison.  This lets us find our New York entry regardless of case.  Now we have a better chance of finding the city when the user searches for it.

This is a very handy technique that also works with HashSet<T>.

Hope this helps.

Advertisements

December 14, 2011

Ignoring Unit Tests

Filed under: .NET,C#,Visual Studio — Larry Parker @ 11:19 pm

Have you ever had a unit test that you didn’t want executed as part of your team’s test runs?  For example, if it requires external data but you haven’t yet set up the test database.  Or you’ve been using a unit test as a workbench for developing some code that you’re interacting with in the debugger and don’t really want it to be run by others.

Up until recently, I would either comment out the [TestMethod] attribute or comment out the entire test method’s code.

But there’s a better way, as a colleague of mine recently advised – the [Ignore] attribute.

Decorating your test method with this attribute will prevent it from being run.

The nice thing about this is your test code will still be compiled and refactored with the rest of your codebase.

When you do want the test to run while you’re working with it, just uncomment the [Ignore] attribute.  Then when you’re ready to check in your test, comment it back and you’re all set to go.

Hope this helps.

Blog at WordPress.com.