C# Collections
Storing and managing groups of data
📦 What are Collections?
Collections are data structures that store multiple items together. They provide flexible ways to organize, search, and manipulate groups of related data like lists, dictionaries, and sets in your programs.
// Simple List example
using System.Collections.Generic;
List<string> fruits = new List<string>();
fruits.Add("Apple");
fruits.Add("Banana");
Common Collection Types
List<T>
Dynamic array of items
List<int> numbers = new List<int>();
numbers.Add(10);
Dictionary<K,V>
Key-value pairs
Dictionary<string, int> ages;
ages["John"] = 25;
Queue<T>
First-in, first-out
Queue<string> queue;
queue.Enqueue("First");
Stack<T>
Last-in, first-out
Stack<int> stack;
stack.Push(1);
🔹 List<T> - Dynamic Arrays
The List<T> collection in C# functions as a dynamic, type-safe array that automatically resizes. It provides methods like Add(), Remove(), Find(), and Sort(). Unlike arrays, Lists grow as needed, making them perfect for scenarios where the number of elements is unknown. They are the go-to choice for ordered, modifiable collections of objects.
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
// Create a list
List<string> cities = new List<string>();
// Add items
cities.Add("New York");
cities.Add("London");
cities.Add("Tokyo");
// Access by index
Console.WriteLine($"First city: {cities[0]}");
// Count items
Console.WriteLine($"Total cities: {cities.Count}");
// Check if contains
bool hasLondon = cities.Contains("London");
Console.WriteLine($"Has London: {hasLondon}");
// Remove item
cities.Remove("London");
// Loop through list
foreach (string city in cities)
{
Console.WriteLine(city);
}
}
}
Output:
First city: New York
Total cities: 3
Has London: True
New York
Tokyo
🔹 Dictionary<TKey, TValue>
A Dictionary<TKey, TValue> in C# stores data as unique key-value pairs for extremely fast lookups. Each key must be unique. Use Add() or the indexer to insert, and retrieve values via the key. It’s implemented as a hash table, offering near O(1) access. Ideal for caches, settings, or any data where quick access by a unique identifier is required.
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
// Create dictionary
Dictionary<string, int> studentGrades = new Dictionary<string, int>();
// Add key-value pairs
studentGrades.Add("Alice", 95);
studentGrades.Add("Bob", 87);
studentGrades["Charlie"] = 92; // Alternative syntax
// Access value by key
Console.WriteLine($"Alice's grade: {studentGrades["Alice"]}");
// Check if key exists
if (studentGrades.ContainsKey("Bob"))
{
Console.WriteLine($"Bob's grade: {studentGrades["Bob"]}");
}
// Loop through dictionary
foreach (KeyValuePair<string, int> student in studentGrades)
{
Console.WriteLine($"{student.Key}: {student.Value}");
}
// Count items
Console.WriteLine($"Total students: {studentGrades.Count}");
}
}
Output:
Alice's grade: 95
Bob's grade: 87
Alice: 95
Bob: 87
Charlie: 92
Total students: 3
🔹 Queue<T> - First In, First Out
The Queue<T> collection in C# follows the First-In-First-Out (FIFO) principle, like a real-world line. Elements are added with Enqueue() and removed with Dequeue(). Peek views the front item without removal. Queues are excellent for task scheduling, message processing, or breadth-first search algorithms where order of processing matters.
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
// Create queue
Queue<string> customers = new Queue<string>();
// Add to queue (Enqueue)
customers.Enqueue("Customer 1");
customers.Enqueue("Customer 2");
customers.Enqueue("Customer 3");
Console.WriteLine($"Customers in queue: {customers.Count}");
// Peek at first item (without removing)
string next = customers.Peek();
Console.WriteLine($"Next customer: {next}");
// Remove from queue (Dequeue)
string served = customers.Dequeue();
Console.WriteLine($"Serving: {served}");
Console.WriteLine($"Remaining: {customers.Count}");
// Process remaining
while (customers.Count > 0)
{
Console.WriteLine($"Serving: {customers.Dequeue()}");
}
}
}
Output:
Customers in queue: 3
Next customer: Customer 1
Serving: Customer 1
Remaining: 2
Serving: Customer 2
Serving: Customer 3
🔹 Stack<T> - Last In, First Out
The Stack<T> collection in C# follows the Last In, First Out (LIFO) principle, making it ideal for tracking sequential operations. Each new item is "pushed" onto the top, while the most recent item is the first to be "popped" off—perfect for implementing undo/redo functionality, managing call histories, or processing tasks in reverse order. For example, in text editors, each action like "Save file," "Edit text," or "Open file" can be stored and undone sequentially. The stack ensures operations are reversed in the exact opposite order they were performed, maintaining workflow integrity and preventing data corruption.
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
// Create stack
Stack<string> actions = new Stack<string>();
// Add to stack (Push)
actions.Push("Open file");
actions.Push("Edit text");
actions.Push("Save file");
Console.WriteLine($"Actions in stack: {actions.Count}");
// Peek at top item
string lastAction = actions.Peek();
Console.WriteLine($"Last action: {lastAction}");
// Remove from stack (Pop)
Console.WriteLine("\nUndo operations:");
while (actions.Count > 0)
{
string undo = actions.Pop();
Console.WriteLine($"Undoing: {undo}");
}
Console.WriteLine($"\nRemaining actions: {actions.Count}");
}
}
Output:
Actions in stack: 3
Last action: Save file
Undo operations:
Undoing: Save file
Undoing: Edit text
Undoing: Open file
Remaining actions: 0
🔹 HashSet<T> - Unique Items
HashSet<T> is a high-performance C# collection designed to store only unique elements, automatically eliminating duplicates. It uses hash-based lookups for lightning-fast searches, inserts, and removals—ideal for managing distinct datasets like user IDs, tags, or IP addresses. For instance, when handling article tags such as "C#," "Programming," and "Tutorial," a HashSet ensures no repetition while enabling quick checks (e.g., `Contains("C#")`) and efficient set operations like unions or intersections. This makes it indispensable for applications requiring data deduplication, membership testing, or maintaining unique inventories.
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
// Create HashSet
HashSet<string> tags = new HashSet<string>();
// Add items
tags.Add("C#");
tags.Add("Programming");
tags.Add("Tutorial");
tags.Add("C#"); // Duplicate - won't be added
Console.WriteLine($"Unique tags: {tags.Count}");
// Check if contains
bool hasCSharp = tags.Contains("C#");
Console.WriteLine($"Has C#: {hasCSharp}");
// Display all tags
Console.WriteLine("\nAll tags:");
foreach (string tag in tags)
{
Console.WriteLine($"- {tag}");
}
// Remove item
tags.Remove("Tutorial");
Console.WriteLine($"\nAfter removal: {tags.Count} tags");
}
}
Output:
Unique tags: 3
Has C#: True
All tags:
- C#
- Programming
- Tutorial
After removal: 2 tags