C# Dictionary

In C# there is an object called Dictionary<TKey, TValue> that can be used to store data.  The Dictionary<TKey, TValue> is essentially a collection of KeyValuePair<TKey, TValue> objects.

C# Dictionary Example 1 – A word dictionary

In this example, we create a simple dictionary with a few words and there definitions and show you how they are accessed.

using System;
using System.Collections.Generic;
using System.Linq;

namespace DictionaryExample
{
    class Program
    {
        static void Main(string[] args)
        {
            Dictionary<String, String> words = new Dictionary<string, string>();
            words.Add("Hello", "An expression or gesture of greeting.");
            words.Add("Goodbye", "A concluding remark or gesture at parting.");
            words.Add("Computer", "A programmable usually electronic device that can store, retrieve, and process data.");
            words.Add("Friend", "One attached to another by affection or esteem");

            Console.WriteLine("Word - Definition");
            Console.WriteLine("===================================================");
            foreach (KeyValuePair<string, string> pair in words)
            {
                Console.WriteLine(string.Format("{0} - {1}", pair.Key, pair.Value));
            }
        }
    }
}

Accessing values in a C# Dictionary

You can access the value using the key. In the case of our word dictionary, the word is the key and the definition is the value.

While you could access the value as follows, there is a problem with the below method.

    private string GetDefinition(String inWord, Dictionary<String, String> inDictionary)
    {
        return inDictionary[inWord];
    }

Do you know what the problem is?  Right, it doesn’t handle a missing value.  If the value doesn’t exist, this will throw a KeyNotFoundException.

Handling a missing value in a C# Dictionary

There are two ways to prevent the KeyNotFoundException.

Method 1 – Use TryGetValue()

TryGetValue() return a bool It takes in the Key and also an out reference. It populates the out reference. Here is an example.

    private string GetDefinition(String inWord, Dictionary<String, String> inDictionary)
    {
        string retVal;
        // String is set to null if the value is not found
        return inDictionary.TryGetValue(inWord, out retVal) ? retVal : ;
    }

I am not a big fan of how the TryGetValue() function was implemented to return a bool However, I understand why it was implemented to return a bool. One might wonder why it returns bool. You may be thinking that TryGetValue() could return a value if found, null otherwise, right? Wrong! Reason 1 – Don’t forget that the value might actually be null. Reason 2 – While this Dictionary used a nullable type, string, another implementation might implement using a type that is not nullable, such as int.

Method 2 – Using ContainsKey()

Alternately you could check if the value exists first using ContainsKey(). Here is an example.

    private string GetDefinition(String inWord, Dictionary<String, String> inDictionary)
    {
        return inDictionary.ContainsKey(inWord) ? inDictionary[inWord] : string.Empty;
    }

I prefer this because to me, it is more readable than the TryGetValue() function, but feel free to make your own opinion.

Looping through a C# Dictionary

Now imagine you wanted to get all the words and their definitions that start with a certain letter. In this case you are creating a Dictionary that is a subset of the full Dictionary. You could do this with a foreach loop. Notice that the object in the foreach loop is a KeyValuePair.

        private Dictionary<String,String> GetWordsAndDefinitionsWhereWordsStartWith(Dictionary<String, String> inDictionary, char inChar)
        {
            Dictionary<String, String> wordsAndDefinitionsWhereWordsStartWithC = new Dictionary<string, string>();
            foreach (KeyValuePair<string, string> pair in inDictionary)
            {
                if (pair.Value.StartsWith(inChar.ToString(), StringComparison.CurrentCultureIgnoreCase))
                    wordsAndDefinitionsWhereWordsStartWithC.Add(pair.Key, pair.Value);
            }
            return wordsAndDefinitionsWhereWordsStartWithC;
        }

You could alternately use LINQ against the C# Dictionary to get the method body to be a single line.

    private Dictionary<String,String> GetWordsAndDefinitionsWhereWordsStartWith(Dictionary<String, String> inDictionary, char inChar)
    {
        return inDictionary.Where(pair => pair.Value.StartsWith(inChar.ToString(), StringComparison.CurrentCultureIgnoreCase)).ToDictionary(pair => pair.Key, pair => pair.Value);
    }

You could just get the words and not the definitions in a List<String> as well.

    private List<String> GetWordstartingWith(Dictionary<String, String> inDictionary, char inChar)
    {
        List<String> wordsStartingWith = new List<String>();
        foreach (KeyValuePair<string, string> pair in inDictionary)
        {
            if (pair.Value.StartsWith(inChar.ToString(), StringComparison.CurrentCultureIgnoreCase))
                wordsStartingWith.Add(pair.Key);
        }
        return wordsStartingWith;
    }

Again, you could use LINQ against the C# Dictionary to make this function one line.

    private List<String> GetWordstartingWith(Dictionary<String, String> inDictionary, char inChar)
    {
        return (from pair in inDictionary where pair.Value.StartsWith(inChar.ToString(), StringComparison.CurrentCultureIgnoreCase) select pair.Key).ToList();
    }

References

Leave a Reply

How to post code in comments?