Table of Contents#
- Introduction to
Dictionary<TKey, TValue>.Item[]Property - Syntax of the
Item[]Property - How the
Item[]Property Works (Get/Set Behaviors) - Example Usage of the
Item[]Property - Common Scenarios for Using the
Item[]Property - Best Practices with the
Item[]Property - Common Pitfalls & How to Avoid Them
- 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. ThrowsKeyNotFoundExceptionifkeydoes not exist. - Setter: Updates the value for
key(if it exists) or adds a new key-value pair (ifkeyis new).
3. How the Item[] Property Works (Get/Set Behaviors)#
Get Behavior#
When retrieving a value (e.g., var value = myDict[key]):
- The dictionary checks if
keyexists (using its hash code and equality comparison). - If
keyexists, the associatedTValueis returned. - If
keydoes not exist, aKeyNotFoundExceptionis thrown.
Set Behavior#
When assigning a value (e.g., myDict[key] = newValue):
- If
keyexists, its value is overwritten withnewValue. - If
keydoes 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
ContainsKeybefore accessing the indexer. - Preferring
TryGetValue(more performant thanContainsKey+ 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>(fromSystem.Collections.Concurrent). - Or, synchronize access with
lockstatements.
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#
- Microsoft Docs:
Dictionary<TKey, TValue>.Item[]Property - Microsoft Docs:
Dictionary<TKey, TValue>Class - Microsoft Docs:
ConcurrentDictionary<TKey, TValue>Class
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.