Start learning free

LESSON 101 OF 347 · DICTIONARIES

Accessing Dictionary Values in C#: Indexer and TryGetValue

Lesson Read the full explanation

In Java, you access values in a HashMap using the get(key) method:

Dictionary<string, int> scores = new Dictionary<string, int>();
scores["Alice"] = 95;
scores["Bob"] = 87;

int aliceScore = scores["Alice"];  // 95
int bobScore = scores["Bob"];      // 87

If the key doesn't exist, get() returns null. Use getOrDefault() to provide a fallback:

int score = scores.GetValueOrDefault("Diana", 0);  // returns 0 if not found

Check if a key exists with containsKey():

if (scores.ContainsKey("Alice")) {
    Console.WriteLine(scores["Alice"]);
}

Assignment
Follow the Coding Tutorial and access Alice's score from scores!


Hint
Use scores.get("Alice") and assign it to aliceScore.

STEP 1 OF 1
    Ctrl + Enter to check

    C# · DICTIONARIES

    Accessing Dictionary Values in C#, explained

    Reading a value by key

    To read a value from a Dictionary<TKey, TValue>, put the key in square brackets, using the same indexer you use to store values:

    Dictionary<string, int> scores = new Dictionary<string, int>();
    scores["Alice"] = 95;
    scores["Bob"] = 87;
    
    int aliceScore = scores["Alice"];  // 95
    int bobScore = scores["Bob"];      // 87
    

    The result has the dictionary's value type, so for a Dictionary<string, int> you can store it straight into an int. There is no get method to call. Code ported from Java uses get(key), and that doesn't exist on a C# dictionary.

    When the key is missing

    This is the main difference from other languages. Reading a key that isn't in the dictionary does not give you null or a default value. The indexer throws a KeyNotFoundException:

    int diana = scores["Diana"];  // throws KeyNotFoundException
    

    That is deliberate. The indexer assumes the key is there, and a missing key is treated as a bug. When a key might be absent, use one of three safer patterns.

    ContainsKey

    Ask first, then read:

    if (scores.ContainsKey("Alice")) {
        Console.WriteLine(scores["Alice"]);
    }
    

    This works, but it looks the key up twice, once to check and once to read.

    TryGetValue

    TryGetValue checks and reads in one call. It returns a bool that says whether the key was found, and hands the value back through an out parameter:

    if (scores.TryGetValue("Bob", out int bob)) {
        Console.WriteLine(bob);  // 87
    }
    
    bool found = scores.TryGetValue("Diana", out int diana);
    Console.WriteLine(found);    // False
    Console.WriteLine(diana);    // 0
    

    When the key is missing, the out variable is set to the default of the value type: 0 for int, null for a string or other reference type. Always test the returned bool instead of guessing from the value, because a stored value can also be 0.

    GetValueOrDefault

    When all you want is a fallback, GetValueOrDefault is the shortest form:

    int score = scores.GetValueOrDefault("Diana", 0);  // 0 when not found
    int other = scores.GetValueOrDefault("Diana");     // also 0, the default for int
    

    Without the second argument it falls back to the type's default value. It doesn't add the key to the dictionary.

    Choosing between the three

    Use the plain indexer when the key must be there and a missing one means a mistake in your program: the exception points straight at the problem. Use TryGetValue when you need to do different things depending on whether the key exists. Use GetValueOrDefault when a sensible fallback value exists, such as 0 for a missing score or an empty string for a missing name.

    Keys and values on their own

    Sometimes you want every key or every value rather than one lookup. The Keys and Values properties give you each as a collection:

    foreach (string name in scores.Keys) {
        Console.WriteLine(name + ": " + scores[name]);
    }
    
    foreach (int value in scores.Values) {
        Console.WriteLine(value);
    }
    

    Looping over the dictionary itself, as in foreach (var pair in scores), gives pair.Key and pair.Value together and avoids the extra lookup in the first loop.

    Case and spelling

    String keys are compared exactly, including case. scores["alice"] is not the same key as scores["Alice"], and with the dictionary above it throws.

    The exercise, step by step

    The lesson starts with a scores dictionary that already has three students. The task is to read Alice's score from it.

    1. Declare an int variable named aliceScore below the dictionary.
    2. Assign it scores["Alice"]. The key is the string "Alice", and the value that comes back is 95. It is safe to use the plain indexer, because the dictionary above was built with that key.
            Dictionary<string, int> scores = new Dictionary<string, int>();
            scores["Alice"] = 95;
            scores["Bob"] = 87;
            scores["Charlie"] = 72;
    
            int aliceScore = scores["Alice"];
    

    Common mistakes

    • Calling get. C# uses the indexer, scores["Alice"], not scores.get("Alice").
    • Expecting null for a missing key. The indexer throws instead. Use TryGetValue or GetValueOrDefault for keys that may be absent.
    • Using the wrong type. An int variable can hold the value from a Dictionary<string, int>. Declaring it as string doesn't compile.
    • Misspelling or mis-casing the key. "alice" and "Alice" are different keys.
    • Reading before storing. If the dictionary doesn't yet hold the key at the moment of the read, the read throws, so keep the assignments above it.

    Key takeaways

    • d[key] reads the value for a key.
    • A missing key makes the indexer throw KeyNotFoundException.
    • ContainsKey, TryGetValue and GetValueOrDefault handle keys that might be missing.
    • String keys are case-sensitive.
    Keep going with C#About 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free