Start learning free

LESSON 129 OF 674 · DICTIONARIES

Reading a Missing Dictionary Key in C# with GetValueOrDefault

Lesson Read the full explanation

TL ; DR:

d.GetValueOrDefault(key, 0) gives the key's value, or 0 when the key is missing.


Dictionary<string, int> points = new Dictionary<string, int>();
points["Ana"] = 7;

Console.WriteLine(points.GetValueOrDefault("Ana", 0));   // 7
Console.WriteLine(points.GetValueOrDefault("Ben", 0));   // 0


Full lesson:

A missing key often means "none yet". A player with no points yet has 0 points.

points["Ben"] can't say that. It throws a KeyNotFoundException.

GetValueOrDefault takes a key and a default. It gives the key's value when the key is there. It gives the default when it isn't.

Reading this way doesn't add the key. points still has one key afterwards.

It does what this if with ContainsKey does, in one line:

int score = 0;
if (points.ContainsKey("Ben")) {
    score = points["Ben"];
}

Your task

stock counts the fruit in a shop. The code reads and prints the pears.

There are no plums yet. Read "plums" with GetValueOrDefault and 0 as the default. Store it in an int named plums.

Then print the plums line, the same way as the pears line.

Expected output:

We have 2 pears
We have 0 plums
STEP 1 OF 2
    Ctrl + Enter to check

    C# · DICTIONARIES

    Dictionary Default Value in C#, explained

    A missing key often means "none yet"

    Think of a shop that counts its fruit. If there are no plums in stock, the shop has zero plums, and the dictionary may simply have no "plums" key. But stock["plums"] cannot say zero. Reading a key that is not in a Dictionary throws a KeyNotFoundException.

    The method GetValueOrDefault(key, defaultValue) solves this. It returns the key's value when the key is there, and the default you pass when it is not.

    Dictionary<string, int> stock = new Dictionary<string, int>();
    stock["apples"] = 5;
    Console.WriteLine(stock.GetValueOrDefault("apples", 0));
    Console.WriteLine(stock.GetValueOrDefault("plums", 0));
    Console.WriteLine(stock.Count);
    
    5
    0
    1
    

    The last line matters: reading with GetValueOrDefault does not add the key. After asking for plums, stock still has one key. In a file of your own, add using System; and using System.Collections.Generic;.

    The longer way to write it

    The method replaces this if:

    int plums = 0;
    if (stock.ContainsKey("plums")) {
        plums = stock["plums"];
    }
    

    Both versions give the same plums. The method says it in one line, and the dictionary is searched once.

    A common use: counting

    Because the default stands in for "none yet", GetValueOrDefault is the natural tool for counting. To count how often each word appears, read the old count, add one, and store it back:

    Dictionary<string, int> counts = new Dictionary<string, int>();
    foreach (string w in new[] {"red", "blue", "red"}) {
        counts[w] = counts.GetValueOrDefault(w, 0) + 1;
    }
    

    A word seen for the first time starts from 0 and becomes 1. At the end, counts holds blue with 1 and red with 2.

    The exercise, step by step

    stock holds 5 apples and 2 pears, and the code already prints the pears line. There are no plums.

    1. Read the plums with a default. Call stock.GetValueOrDefault("plums", 0) and store the result in an int named plums. The key is missing, so plums is 0.
    2. Print the plums line. Copy the pears line and use plums in place of pears.
    Dictionary<string, int> stock = new Dictionary<string, int>();
    stock["apples"] = 5;
    stock["pears"] = 2;
    int pears = stock["pears"];
    Console.WriteLine("We have " + pears + " pears");
    int plums = stock.GetValueOrDefault("plums", 0);
    Console.WriteLine("We have " + plums + " plums");
    
    We have 2 pears
    We have 0 plums
    

    The pears line reads with stock["pears"] because that key exists. The plums line needs the safe version.

    Details and traps

    The default has to fit the value type. For a Dictionary<string, int> it is an int, and for a Dictionary<string, string> it is a string, such as "". The compiler checks this, so a mismatched default does not build.

    • The default is yours to pick. Zero suits counts. For a different job, pass something else: stock.GetValueOrDefault("plums", -1) gives -1, which can mean "not tracked".
    • Leaving the default out. GetValueOrDefault("plums") uses the default for the value type: 0 for int, and null for a string value. A null can cause a NullReferenceException later, so give a default when you can.
    • It only reads. To save a result, assign it: stock["plums"] = 3;.
    • The default is not stored. A later stock.ContainsKey("plums") is still false.
    • A stored zero looks like a missing key. If a key is present with the value 0, the read also gives 0. Use ContainsKey when that difference matters.

    Key takeaways

    • d.GetValueOrDefault(key, 0) gives the value, or 0 for a missing key.
    • It never throws and never adds the key.
    • Plain d[key] throws a KeyNotFoundException for a missing key.
    • It is a short form of ContainsKey plus a read.
    Keep going with C#500+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free