CodeGym /Courses /C# SELF /Dictionary: Dictionary<...

Dictionary: Dictionary<TKey, TValue>

C# SELF
Level 27 , Lesson 3
Available

1. Introduction

Imagine you're the owner of a small shop, and you have a list of products. Each product has its own unique SKU (like ART-001, ART-002) and, of course, a name, price, and stock quantity.

If you stored all this in a List<T>, where T is, say, our future Product class, then to find a product with SKU ART-005, you'd have to go through the whole list:
"Is this ART-001? Nope. Is this ART-002? Nope... Oh, this is ART-005! Found it!"
If you have 10 products, that's fine. But what if you have 10,000? Or 100,000? Searching for each product would take forever. Your customer would have to wait ages for you to find their favorite pack of cookies. Not cool!

We need a way to instantly jump to the product we want if we know its unique SKU, without checking all the others. So, we need some kind of "key" that points straight to the right "value."

Meet Dictionary

And that's where Dictionary<TKey, TValue> comes in! Think of it not just as a list, but as a super-smart phone book. In a regular phone book, you look up a phone number (the value) by a person's name (the key). You open the book to "A," then look for "Alex," and boom, there's his number. You don't have to flip through every number until you find the right one.

Same deal with Dictionary (which literally means "dictionary" in English): it stores data as "key-value" pairs.

  • Key (TKey): This is a unique identifier for each item. It's like a name in a phone book or a product SKU. You'll use this key to look up the value you want. The key has to be unique within the dictionary. If you try to add an item with a key that already exists, Dictionary won't let you.
  • Value (TValue): This is the actual data you want to store. It could be a phone number, product price, term description—whatever!

The letters TKey and TValue in the angle brackets <TKey, TValue> mean that Dictionary is a generic collection. You get to decide what type your key is and what type your value is. The key could be a string (like a name or SKU), int (user ID), or even your own class. The value could be int, string, double, or even a whole object.

The advantage? Instant access! Thanks to its special internal structure (a hash table, if you wanna get technical—but don't worry, you don't need to know how it works yet), Dictionary lets you find a value by key in super short time, no matter if there are ten items or a million. It's like a super-index in a giant library: you say, "I need the C# book," and they instantly show you where it is, without making you check every shelf.

Let's get right to it! We'll build out our project by making an interactive "C# Terms Dictionary" to help us remember new concepts.

2. Syntax Basics: Creating a Dictionary

It all starts the usual way: declare a variable, but now you gotta specify not one, but two types—the key type (TKey) and the value type (TValue):

// Simple dictionary: key - string (login), value - string (email)
Dictionary<string, string> userEmails = new Dictionary<string, string>();

// Or shorter with var 
var userEmails = new Dictionary<string, string>();

Why do you have to specify both types?
Because C# is a strongly typed language, and the dictionary needs to know what types of keys and values you want to use.

Adding Items

To add a new "key-value" pair, use the Add method. The key has to be unique!

userEmails.Add("john", "john@example.com");
userEmails.Add("mike", "mike@gmail.com");

If you try to add the same key again, the dictionary will get mad and throw an exception.

Accessing Values by Key

The coolest thing about a dictionary is getting a value by its key:

string email = userEmails["john"];
Console.WriteLine(email); // john@example.com

If you try to access a key that doesn't exist, your program will freak out (throw a KeyNotFoundException). We'll check out safer ways to check for a key soon.

Changing a Value by Key

If the key already exists, just assign a new value:

userEmails["john"] = "john@newmail.ru"; // now Vasya's email is changed

If the key wasn't there before, this assignment will create a new item in the dictionary.

User Example

Let's tweak our learning app a bit. We used to store a list of tasks (List<string> tasks;) for a ToDo app. Now, let's add "authorization": each user needs an email.

Here's how it might look:

// UserId is a string, Email is also a string
var users = new Dictionary<string, string>();
users.Add("admin", "admin@myapp.com");
users.Add("alice", "alice@wonderland.com");
users.Add("bob", "bob@builder.com");

Now you can always quickly find any user's email by their login:

Console.WriteLine(users["alice"]); // => alice@wonderland.com

3. Main Methods and Properties of Dictionary

Method/Property Description
Add(key, value)
Adds a new "key-value" pair.
Remove(key)
Removes an item by key.
ContainsKey(key)
Checks if a key exists.
ContainsValue(value)
Checks if a value exists (slow!).
TryGetValue(key, out val)
Safely gets a value by key without throwing exceptions.
Count
The number of "key-value" pairs in the dictionary.
Keys
Collection of all keys.
Values
Collection of all values.

Checking for a Key

The most common (and safest) thing is to check if a key exists first:

if (users.ContainsKey("sara"))
{
    Console.WriteLine(users["sara"]);
}
else
{
    Console.WriteLine("User sara not found!");
}

Safe Way: TryGetValue

The TryGetValue method helps you avoid exceptions:

if (users.TryGetValue("bob", out string email))
{
    Console.WriteLine($"Bob's email: {email}");
}
else
{
    Console.WriteLine("Bob not found!");
}

This is good practice and interviewers love to ask about it—learn it right away! Plus, this method is faster than using ContainsKey + index access.

4. Looping Through a Dictionary: foreach Loop

If you wanna go through all the pairs, use a foreach loop. Each dictionary item is a KeyValuePair<TKey, TValue> object:

foreach (var pair in users)
{
    Console.WriteLine($"Login: {pair.Key}, Email: {pair.Value}");
}

Or, if you wanna be even cooler:

foreach (var (login, email) in users)
{
    Console.WriteLine($"{login}: {email}");
}
// This syntax is available thanks to tuple deconstruction (C# 7+).

5. Removing and Changing Values

To remove a user by login is easy:

users.Remove("alice");

If the key doesn't exist, it'll return false. You can safely try to remove without worrying about exceptions.

To change a user's email:

users["bob"] = "bob@constructor.com";

If the key wasn't there before, a new pair will be created!

6. Handy Properties Keys and Values

If you only need the list of logins (keys) or just emails (values), use the Keys and Values collections:

foreach (string login in users.Keys)
{
    Console.WriteLine("Login: " + login);
}

foreach (string email in users.Values)
{
    Console.WriteLine("Email: " + email);
}

7. Important Dictionary Gotchas

Keys Must Be Unique

You can't add two identical keys. If you try, you'll get an exception. This uniqueness keeps your data safe: one user can't have two emails at once (one record per user).

Key Can't Be null (for string)

For string keys, trying to add a null key will throw an error (ArgumentNullException). If you suddenly don't have a key, think about it—it might mean there's a problem with your data logic.

Why is Dictionary Lookup So Fast?

Dictionary is built "under the hood" on a hash table. That means looking up a key isn't about checking every item in order, but lightning-fast calculation of a special "hash function" and almost direct access to the cell where the value is stored.

What Can You Use as a Key?

  • Any type that correctly implements equality comparison and unique code generation (Equals and GetHashCode() methods).
  • Usually that's string, int, Guid, or your own types (but then you gotta be careful with overriding Equals/GetHashCode, or you might get some wild bugs).

8. Adding a Dictionary to the App

In our mini ToDo app, let's add a user dictionary and make a function to look up emails by login with error handling:

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        // User dictionary: login => email
        var users = new Dictionary<string, string>
        {
            { "admin", "admin@myapp.com" },
            { "alice", "alice@wonderland.com" },
            { "bob", "bob@builder.com" }
        };

        Console.WriteLine("Enter a user login to search for email:");
        string login = Console.ReadLine();

        // Safe email lookup
        if (users.TryGetValue(login, out string email))
        {
            Console.WriteLine($"User {login}'s email: {email}");
        }
        else
        {
            Console.WriteLine($"User {login} not found.");
        }

        // Loop through all users
        Console.WriteLine("\nList of all users:");
        foreach (var pair in users)
        {
            Console.WriteLine($"{pair.Key} => {pair.Value}");
        }
    }
}

9. Typical Beginner Mistakes and Traps

Sometimes you really wanna do this:

// Hoping that if the key doesn't exist, everything will be fine
string value = users["nonexistent"]; // Boom! KeyNotFoundException!

Don't forget: always check if the key exists (ContainsKey or TryGetValue) if you're not 100% sure it's there.

Also remember: looping through values doesn't guarantee they're unique! Two logins could have the same email (if you lost control over value uniqueness, not key uniqueness).

People also mix up methods—for example, trying to remove by value:

users.Remove("bob@builder.com"); // Won't remove! Expects a key, not a value.
2
Task
C# SELF, level 27, lesson 3
Locked
Checking for Keys and Values
Checking for Keys and Values
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION