#1,133 – Initializing a Dictionary with a Collection Initializer

You can initialize a generic Dictionary with a collection initializer as follows:

            // Initialization with collection initializer
            Dictionary<string, int> guys = new Dictionary<string,int> {
                    {"Galileo", 1564},
                    {"Magellan", 1480},
                    {"Voltaire", 1694},
                    {"Kepler", 1571},
                    {"Keaton", 1895}
                };

            foreach (KeyValuePair<string, int> kvp in guys)
                Console.WriteLine("{0} ({1})", kvp.Key, kvp.Value);

1133-001

#1,132 – Using a SortedDictionary

You can use a SortedDictionary<T1,T2> instead of a Dictionary<T1,T2> when you’d like entries sorted in the dictionary by the value of their keys.  Below is an example where we count how many times each letter of the alphabet is found in a particular string.

            string someText = "One cannot think well, love well, " +
                "sleep well, if one has not dined well.";

            SortedDictionary<char, int> charCounter = new SortedDictionary<char, int>();

            foreach (char c in someText)
            {
                if (char.IsLetter(c))
                {
                    char cLower = char.ToLower(c);
                    if (!charCounter.ContainsKey(cLower))
                        charCounter.Add(cLower, 1);
                    else
                        charCounter[cLower]++;
                }
            }

            Console.WriteLine("Found {0} unique letters", charCounter.Keys.Count);

            foreach (KeyValuePair<char, int> kvp in charCounter)
                Console.WriteLine("[{0}] - {1} instances", kvp.Key, kvp.Value);

1132-001

#1,131 – Example of Using a Generic Dictionary

Below is an example of using a generic dictionary to count how many times each type of letter appears in a passage of text.  The keys are of type char (the letter found) and the values are of type int (# times found).

            string someText = "One cannot think well, love well, " +
                "sleep well, if one has not dined well.";

            Dictionary<char, int> charCounter = new Dictionary<char, int>();

            foreach (char c in someText)
            {
                if (!charCounter.ContainsKey(c))
                    charCounter.Add(c, 1);
                else
                    // charCounter[c] is of type int,
                    //   c is of type char
                    charCounter[c]++;
            }

            Console.WriteLine("Found {0} unique characters", charCounter.Keys.Count);

            foreach (KeyValuePair<char, int> kvp in charCounter)
                Console.WriteLine("[{0}] - {1} instances", kvp.Key, kvp.Value);

1131-001

#1,130 – Checking to See if a Generic Dictionary Already Contains a Key

When using a generic dictionary, you can use the square bracket syntax to retrieve the value for a specified key.  This will only work, however, if that particular key has already been added to the dictionary.  When you first create the dictionary, it contains no keys.

If you try retrieving a value for a key that doesn’t already exist in the dictionary, you’ll get a KeyNotFoundException at runtime.

1130-01

You can avoid this error by first checking to the presence of a key using the ContainsKey method of the dictionary.  If this method returns true, you can safely retrieve the value of the key using the square bracket syntax.

            Dictionary<char, int> charCounter = new Dictionary<char, int>();

            int numEs = charCounter.ContainsKey('e') ? charCounter['e'] : 0;

 

#1,129 – Generic Dictionary Basics

The generic dictionary class, System.Collections.Generic.Dictionary<TKey,TValue>, allows you to store a collection of key/value pairs, where the both the keys and the values have a particular type.

You specify types for the keys and values when you declare an instance of the dictionary, creating a constructed type.  The example below creates an instance of a dictionary that stores an integer value for each of a set of character values.

            Dictionary<char, int> charCounter = new Dictionary<char, int>();

By default, the collection contains no entries–no key/value pairs.  You add an entry using the Add method, specifying a new key to be added, along with its value.  Note that the key is of type char and the value is of type int.

            charCounter.Add('x', 12);

If a dictionary already contains a particular key, you can retrieve the value using square bracket syntax.

            int numXs = charCounter['x'];

 

#1,118 – foreach Works with Iterator Returned by yield

You can use the yield keyword in a method to implement an iterator.  The method in which it is defined returns an IEnumerable or IEnumerator.  The resulting iterator can be consumed using the foreach statement.

Below is an example of a method that returns an IEnumerable<T> which can then be iterated upon using a foreach statement.

        static IEnumerable<Dog> DogsWithKids(IEnumerable<Dog> dogList)
        {
            foreach (Dog d in dogList)
            {
                yield return d;
                yield return new Dog(d.Name + " Jr.",
                                     Math.Max(d.Age - 3, 1));
            }
        }

        static void Main(string[] args)
        {
            List<Dog> myDogs = new List<Dog>
                {
                    new Dog {Name = "Kirby", Age = 15},
                    new Dog {Name = "Ruby", Age = 2}
                };

            // Iterate through dogs w/offsprings
            foreach (Dog d in DogsWithKids(myDogs))
                Console.WriteLine(d);

            Console.ReadLine();
        }

The result is a sequence with twice as many elements as the original List<T>.

1118-001

#1,117 – foreach Requires IEnumerable Implementation

The foreach statement works on an object that implements IEnumerable<T> or IEnumerable.  It also works on an object whose type has a public GetEnumerator method that returns an IEnumerator<T> or IEnumerator.

Below, we’ve defined a new class that implements IEnumerable<T>.

    public class DogPack : IEnumerable<Dog>
    {
        private List<Dog> thePack;

        public DogPack()
        {
            thePack = new List<Dog>();
        }

        public void Add(Dog d)
        {
            thePack.Add(d);
        }

        // Remove arbitrary dog
        public void Cull()
        {
            if (thePack.Count == 0)
                return;

            if (thePack.Count == 1)
                thePack.RemoveAt(0);
            else
            {
                Random rnd1 = new Random();
                int indRemove = rnd1.Next(thePack.Count);
                thePack.RemoveAt(indRemove);
            }
        }

        // IEnumerable<T> implementation

        public IEnumerator<Dog> GetEnumerator()
        {
            return thePack.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }

We can now use foreach to iterate on an instance of this class.

            DogPack pack = new DogPack();
            pack.Add(new Dog("Lassie", 8));
            pack.Add(new Dog("Shep", 12));
            pack.Add(new Dog("Kirby", 10));
            pack.Add(new Dog("Jack", 15));
            pack.Cull();

            // Who's left?
            foreach (Dog d in pack)
                Console.WriteLine(d);

1117-001