Shalom!
Sometime ago I mentioned usage dictionaries to workaround lack of possibility to use variable which name is stored in another variable. It is useful trick (at least for me – beginner) but dictionaries may be employed to perform multitude of tasks. So, to preserve my newly gained skills I present most important aspects of dictionaries.
The main idea behind dictionaries is to have a structure that holds certain values tied to certain keys. It may be depicted as 1-D array which instead of numeric indexes uses any type of variables as example below shows:

INITIALISING A DICTIONARY
Dictionary is a collection. To use it you need to include appropriate namespace: System.Collections.Generic. Definition of a dictionary must specify three things: its name, type of key and type of stored value:
|
using System.Collections.Generic; ... Dictionary<string, int> Stock = new Dictionary<string, int>(); |
The example below initialises empty dictionary – it was created using a constructor that doesn’t take any arguments. However, this is not the only option. Visual Studio suggest six different variations of constructor. You can set initial size of a dictionary, method of comparing keys – I am not going to describe each constructor as Visual Studio does that sufficiently. I just mention that it is possible to initialise a dictionary using a constructor that takes existing dictionary as an argument. Such action will copy of an argument dictionary to the newly created one. I find it most useful.
|
Dictionary<string, int> OldStock = new Dictionary<string, int>(); Dictionary<string, int> Stock = new Dictionary<string, int>(OldStock); |
OPERATIONS INSIDE DICTIONARY
Adding new element
It is that simple that I was tempted to omit that, but for sake of conscientiousness here’s a quick example. To add a new element to a dictionary you need to use Add method and provide key and value of new element:
|
Dictionary<string, int> Stock = new Dictionary<string, int>(); Stock.Add("Nails", 39); Stock.Add("Bolts", 21); Stock.Add("Glue", 76); Stock.Add("Bricks", 6); Stock.Add("Whatever", 99); |
Accessing/modifying value of an element
Again, it’s very simple. Code below illustrates that:
|
Console.WriteLine("We have " + Stock["Nails"] + " nails on stock."); Stock["Nails"] += 10; Console.ReadKey(); |
Looping through whole dictionary
It is no secret that to run through whole dictionary you have to use foreach loop. To correctly design that loop you need to use KeyValuePair as an iterator. It is also necessary to provide types of keys and values accordingly to dictionary we want to loop through.
|
Console.WriteLine("Current stock items:"); foreach(KeyValuePair<string, int> StockItem in Stock) { Console.WriteLine(StockItem.Key + ": " + StockItem.Value); } Console.ReadKey(); /* Output: Current stock items: Nails: 49 Bolts: 21 ... Whatever: 99 */ |
Other useful methods for dictionaries
Here are some other methods that you may find useful. These are quite simple operations so their description will be presented together with the code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
//ContainsKey(key) - checks if a specified key is present in a dictionary string RequestedItem = "Nails"; if(Stock.ContainsKey(RequestedItem)) { Console.WriteLine(RequestedItem + " can be found on Stock. There are " + Stock[RequestedItem] + " on Stock."); } else { Console.WriteLine("Sorry, there are no " + RequestedItem + " on stock."); } //Count() - returns total number of key/value items in a dictionary Console.WriteLine("There are currently "+Stock.Count()+" different articles in stock"); //Remove(key) - removes key/value item from a dictionary Stock.Remove("Bricks"); Console.WriteLine("Bricks are no longer stored in Stock"); //Clear - removes all key/value items from a dictionary Stock.Clear(); Console.WriteLine("Stock has been cleared."); |
EXAMPLE OF USAGE
So, now we have basic comprehension of what dictionaries are and how to use them. I am sure you will easily find a task that which can utilise dictionaries. But to provide an example I’ll show one possible implementation.
Currently, I am writing an application which will allow user to switch between different languages (dictionaries, languages – that obvious, isn’t it?). The plan is to store language data in an XML file and load its content to a dictionary. Then, instead of hard-coding every word that is visible for end-user the program will display data stored in the dictionary. Here’s a class that allows that:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
|
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.IO; using System.Xml; namespace MechPro_Manager { public static class Language { public static Dictionary<string, string> LoadedLanguage = new Dictionary<string, string>(); public static void LoadLanguage(string SetLanguage, string Area) { string Source = @"Resources\" + SetLanguage + ".xml"; //MessageBox.Show("Loading language pack:\nFile: " + Source + "\nArea: " + Area); XmlDocument RetrievedLanguage = new XmlDocument(); RetrievedLanguage.Load(Source); XmlNodeList SettingsList = RetrievedLanguage.SelectNodes("Language/"+Area); XmlNode Setting = SettingsList[0]; foreach(XmlNode CurrentSetting in Setting.ChildNodes) { string SettingName = CurrentSetting.Name; string SettingValue = CurrentSetting.InnerText; if(!LoadedLanguage.ContainsKey(CurrentSetting.Name)) { LoadedLanguage.Add(CurrentSetting.Name, CurrentSetting.InnerText); } else { LoadedLanguage[CurrentSetting.Name] = CurrentSetting.InnerText; } //MessageBox.Show("Setting: " + SettingName + "\nValue: " + SettingValue); } } public static bool ExistLanguage(string SetLanguage) { string Source = @"Resources\" + SetLanguage + ".xml"; //MessageBox.Show(Source); if(File.Exists(Source)) { //MessageBox.Show("Settings file exists."); return true; } MessageBox.Show("Language file does not exists!", "Error!"); if(UserSettings.Settings["Language"] == "English") { MessageBox.Show("English language file cannot be loaded. The program will terminate!", "Critical error!", MessageBoxButtons.OK, MessageBoxIcon.Stop); Application.Exit(); } return false; } } } |
The class is static – there’s no need to create various instances as only one language can be displayed. The class has only one property – LoadedLanguage – a dictionary that uses string key to store string values.
There are two methods: method ExistLanguge(string) checks if a language file chosen by user exists. If it does the method returns true and the program continues. If the file doesn’t exist the program displays a warning message. Additionally, if the chosen language is English and its XML file doesn’t exist the program terminates as English is default language.
Another method is used to load specified language to the dictionary. As earlier said the language data is stored in the XML file. That XML file is divided into sections depending on which form it relates to.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
|
<?xml version="1.0" encoding="utf-8" ?> <Language> <MainWindow> <TopMenuMainWindowApp>Application</TopMenuMainWindowApp> <TopMenuMainWindowAppExit>Exit application</TopMenuMainWindowAppExit> <StatusStripMainWindowSQLStatus>SQL status</StatusStripMainWindowSQLStatus> <TopMenuMainWindowAppConnect>Connect to DB</TopMenuMainWindowAppConnect> <CurrentConnectedText>Connected</CurrentConnectedText> <CurrentDisconnectedText>Disconnected</CurrentDisconnectedText> <TopMenuMainWindowAppDisconnect>Disconnect from DB</TopMenuMainWindowAppDisconnect> <TopMenuMainWindowSetup>Setup</TopMenuMainWindowSetup> <TopMenuMainWindowSetupLocal>Local setup</TopMenuMainWindowSetupLocal> </MainWindow> <DBConnection> <DBConnectionDialogTitle>Connect to database...</DBConnectionDialogTitle> <DBConnectionInfoLabel>Provide valid credentials to connect with MySQL database server</DBConnectionInfoLabel> <DBConnectionServerLabel>Server: </DBConnectionServerLabel> <DBConnectionUserLabel>MySQL user: </DBConnectionUserLabel> <DBConnectionPassLabel>Password: </DBConnectionPassLabel> <DBConnectionDatabaseLabel>Database: </DBConnectionDatabaseLabel> <DBConnectionAutoCheckbox>Connect automatically next time</DBConnectionAutoCheckbox> <DBConnectionConnectButton>Connect</DBConnectionConnectButton> <DBConnectionCancelButton>Cancel</DBConnectionCancelButton> <DBConnectionError>MySQL connection error</DBConnectionError> <DBConnectionError0>Given credentials are not valid!</DBConnectionError0> <DBConnectionError1042>Unable to reach specified server!</DBConnectionError1042> <DBConnectionErrorUnknown>Unexpected error!</DBConnectionErrorUnknown> <DBConnectionPassHint>Note that password will not be encrypted!</DBConnectionPassHint> </DBConnection> <ConfirmDisconnect> <ConfirmDisconnectDialogTitle>MySQL database</ConfirmDisconnectDialogTitle> <ConfirmDisconnectDialogMessage>Are you sure to disconnect with current database?</ConfirmDisconnectDialogMessage> <ConfirmDisconnectDialogNotConnected>You are not connected to any database!</ConfirmDisconnectDialogNotConnected> </ConfirmDisconnect> <LocalSetup> <LocalSetupTabsGeneral>General</LocalSetupTabsGeneral> <LocalSetupDialogTitle>Local installation setup</LocalSetupDialogTitle> <LocalSetupSaveButton>Save</LocalSetupSaveButton> <LocalSetupDiscardButton>Discard</LocalSetupDiscardButton> <LocalSetupTabsGeneralInterface>Interface</LocalSetupTabsGeneralInterface> <LocalSetupLanguageLabel>Language: </LocalSetupLanguageLabel> <LocalSetupShowTimerCheck>Show date/time in status bar</LocalSetupShowTimerCheck> </LocalSetup> </Language> |
Method LoadLanguage(string, string) takes as arguments language to load and section of XML file to load. Then it loops through the XML file and creates key/value pairs in the dictionary according to nodes present between specified area. Then these pairs are used in various parts of the program to display labels in specified language.
So, that quick guide through dictionaries would be it for today. Enjoy!
Examples (*.cs)