cyberangles blog

C# | Dictionary.Item[] Property: A Deep Dive into Indexers for Key-Value Pairs

The Dictionary<TKey, TValue> class (from System.Collections.Generic) is a core C# collection for storing key-value pairs, offering O(1) average time complexity for lookups, insertions, and deletions (with a good hash function). A critical feature of Dictionary<TKey, TValue> is its indexer property (formally named Item[]), which enables accessing, modifying, or adding key-value pairs using the familiar square bracket ([]) syntax (e.g., myDict[key]). This blog explores the Item[] property in depth, including syntax, behavior, best practices, and common pitfalls.

2026-06

Table of Contents#

  1. Introduction to Dictionary<TKey, TValue>.Item[] Property
  2. Syntax of the Item[] Property
  3. How the Item[] Property Works (Get/Set Behaviors)
  4. Example Usage of the Item[] Property
  5. Common Scenarios for Using the Item[] Property
  6. Best Practices with the Item[] Property
  7. Common Pitfalls & How to Avoid Them
  8. References

1. Introduction to Dictionary<TKey, TValue>.Item[] Property#

The Item[] property (often called the indexer) in Dictionary<TKey, TValue> provides a convenient way to:

  • Retrieve a value by its key (e.g., var value = myDict[key]).
  • Update the value of an existing key (e.g., myDict[key] = newValue).
  • Add a new key-value pair (e.g., myDict[newKey] = newValue).

While the formal name is Item[], C# allows direct use of [] syntax (e.g., myDict[key]), which is syntactic sugar for accessing the Item[] property.

2. Syntax of the Item[] Property#

The Item[] property is defined with the following signature:

public TValue this[TKey key] { get; set; }
  • Getter: Retrieves the value for key. Throws KeyNotFoundException if key does not exist.
  • Setter: Updates the value for key (if it exists) or adds a new key-value pair (if key is new).

3. How the Item[] Property Works (Get/Set Behaviors)#

Get Behavior#

When retrieving a value (e.g., var value = myDict[key]):

  1. The dictionary checks if key exists (using its hash code and equality comparison).
  2. If key exists, the associated TValue is returned.
  3. If key does not exist, a KeyNotFoundException is thrown.

Set Behavior#

When assigning a value (e.g., myDict[key] = newValue):

  • If key exists, its value is overwritten with newValue.
  • If key does not exist, a new key-value pair (key, newValue) is added.

4. Example Usage of the Item[] Property#

Basic Retrieval & Update#

using System;
using System.Collections.Generic;
 
class Program
{
    static void Main()
    {
        // Create a dictionary of student names (string) and scores (int)
        Dictionary<string, int> studentScores = new Dictionary<string, int>
        {
            { "Alice", 95 },
            { "Bob", 88 }
        };
 
        // 1. Retrieve a value (get)
        int aliceScore = studentScores["Alice"];
        Console.WriteLine($"Alice's score: {aliceScore}"); // Output: Alice's score: 95
 
        // 2. Update a value (set)
        studentScores["Bob"] = 92;
        Console.WriteLine($"Bob's updated score: {studentScores["Bob"]}"); // Output: Bob's updated score: 92
 
        // 3. Add a new key-value pair (set)
        studentScores["Charlie"] = 78;
        Console.WriteLine($"Charlie's score: {studentScores["Charlie"]}"); // Output: Charlie's score: 78
    }
}

Handling Key Existence#

To avoid KeyNotFoundException, check if the key exists (or use TryGetValue):

Option 1: ContainsKey + Indexer#

string keyToCheck = "Dave";
if (studentScores.ContainsKey(keyToCheck))
{
    int score = studentScores[keyToCheck];
    Console.WriteLine($"{keyToCheck}'s score: {score}");
}
else
{
    Console.WriteLine($"{keyToCheck} not found.");
}

Option 2: TryGetValue (Preferred)#

TryGetValue is more performant (avoids two lookups) and handles "key not found" in one operation:

if (studentScores.TryGetValue("Eve", out int eveScore))
{
    Console.WriteLine($"Eve's score: {eveScore}");
}
else
{
    Console.WriteLine("Eve not found. Adding her with a score of 85...");
    studentScores["Eve"] = 85; // Add via indexer
}

5. Common Scenarios for Using the Item[] Property#

The Item[] property excels in:

  • Retrieving Values: When you are confident the key exists (e.g., validated data).
  • Updating Values: Modifying an existing key’s value (e.g., incrementing a counter, updating a user’s profile).
  • Adding New Entries: Inserting a new key-value pair (when the key is unique or overwriting is intentional).

6. Best Practices with the Item[] Property#

1. Check for Key Existence (or Use TryGetValue)#

Avoid KeyNotFoundException by:

  • Using ContainsKey before accessing the indexer.
  • Preferring TryGetValue (more performant than ContainsKey + indexer).

2. Avoid Accidental Overwriting#

The indexer’s set operation overwrites values. To add a key only if it does not exist, use TryAdd (available in .NET Core 2.0+ / .NET 5+):

if (myDict.TryAdd(newKey, newValue))
{
    // Key added successfully
}
else
{
    // Key already exists; handle accordingly
}

3. Thread Safety#

Dictionary<TKey, TValue> is not thread-safe. For multi-threaded scenarios:

  • Use ConcurrentDictionary<TKey, TValue> (from System.Collections.Concurrent).
  • Or, synchronize access with lock statements.

4. Choose Appropriate Key Types#

Ensure the key type implements IEquatable<T> (or overrides GetHashCode/Equals) to avoid lookup failures. For example, use string (implements IEquatable<string>) or a custom type with proper equality logic.

7. Common Pitfalls & How to Avoid Them#

Pitfall 1: Unhandled KeyNotFoundException#

Problem: Accessing a non-existent key via the indexer throws an exception.
Solution: Use ContainsKey or TryGetValue to check for the key first.

Pitfall 2: Accidental Overwriting#

Problem: The indexer’s set operation overwrites values.
Solution: Use TryAdd to add a key only if it does not exist. If overwriting is intentional, document it.

Pitfall 3: Performance Issues with Repeated Lookups#

Problem: Using ContainsKey + indexer causes two lookups.
Solution: Use TryGetValue (performs one lookup).

8. References#

Conclusion#

The Dictionary<TKey, TValue>.Item[] property (indexer) is a powerful tool for managing key-value pairs in C#. By understanding its behavior, following best practices (e.g., TryGetValue, TryAdd), and avoiding common pitfalls, you can write efficient, robust code for data retrieval, updates, and additions.