Back to Blog
C#

C# Dictionary Declaration: Syntax and Initialization

c# dictionary declaration: Learn how to declare a Dictionary in C# with type parameters, initializers, capacity, and custom comparers, plus performance tradeoffs.

DictionaryC# CollectionsCollection InitializerGeneric TypesType Inference
Diagram showing a C# dictionary declaration mapping string keys to integer values with a clean arrow between key and value boxes.

C# Dictionary Declaration: Core Syntax

The Dictionary<TKey, TValue> type is the standard key-value collection in C#. A c# dictionary declaration requires two type parameters: one for the key and one for the value. The most common form looks like this:

Dictionary<string, int> scores = new Dictionary<string, int>();

This declares a dictionary that maps string keys to integer values. The class lives in the System.Collections.Generic namespace, so you need using System.Collections.Generic; unless your project enables implicit usings. Both type parameters are mandatory; there is no non-generic dictionary type you should use in new code.

Declaring with Collection Initializer Values

You can populate a dictionary at declaration time with a collection initializer. Two syntaxes exist: the key-value pair form and the indexer form introduced in C# 6.

Dictionary<string, int> scores = new Dictionary<string, int> { { "Alice", 90 }, { "Bob", 85 } };

The pair form calls Add(key, value) for each entry. A duplicate key throws ArgumentException because Add rejects duplicates. The indexer form assigns through the indexer, so a duplicate key overwrites the previous value instead of throwing:

Dictionary<string, int> scores = new Dictionary<string, int> { ["Alice"] = 90, ["Bob"] = 85 };

Choose the indexer form when you want overwrite semantics or prefer the concise syntax. Use the Add form when duplicate keys should fail fast during initialization.

Declaring with an Initial Capacity

When you know how many entries the dictionary will hold, pass that count to the constructor:

Dictionary<string, int> scores = new Dictionary<string, int>(100);

The capacity is a hint, not a limit. The dictionary grows automatically when you exceed it. Pre-allocating avoids repeated internal array resizes, which matters when the dictionary is populated once in a startup path and then read frequently.

Declaring with a Custom Comparer

The default comparer uses the key type's Equals and GetHashCode methods. For strings, that means case-sensitive comparison. To make keys case-insensitive, pass a StringComparer instance:

Dictionary<string, int> caseInsensitive = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);

With this declaration, caseInsensitive["alice"] and caseInsensitive["Alice"] resolve to the same entry. The comparer is fixed at construction time and cannot be changed later. It affects ContainsKey, TryGetValue, and the indexer.

Using var for Type Inference

For local variables, var shortens the declaration without losing type information:

var scores = new Dictionary<string, int>();

The compiler infers Dictionary<string, int>. This is identical to the explicit form. Use var when the right-hand side makes the type obvious; use the explicit type when the declaration is separated from initialization or when the type name aids readability.

Null Keys and Duplicate Key Behavior

Dictionary<TKey, TValue> permits a single null key for reference types. A null key is stored as one distinct entry. Duplicate keys are rejected by Add and overwritten by the indexer. These behaviors are fixed by the type and cannot be configured, so the declaration itself is where you decide which initialization style matches your intent.

Performance Considerations

The constructor arguments you choose affect runtime behavior. Pre-allocating capacity reduces resizes. The comparer choice affects every lookup: a case-insensitive comparer performs a different comparison than the default ordinal comparer, and the difference is usually small but measurable in tight loops. If you define a custom key type, its GetHashCode implementation determines hash distribution. Poor hash distribution degrades lookups from near-constant time toward linear time, regardless of how the dictionary is declared.

When a Dictionary Is the Right Collection

Use a dictionary when you need fast lookup by a unique key. If you only need sequential access, List<T> is simpler. If insertion order matters, Dictionary does not guarantee it; consider List<KeyValuePair<TKey, TValue>> or a dedicated ordered collection. If keys are small integers, an array indexed by the integer is often faster and more memory-efficient than a dictionary.

c# dictionary declaration: Practical Usage and Code Examples | RYUSLOG DEV