C#’s strong collection types enable developers to store, organize, and manipulate data, crucial for real-world applications like HR systems, payroll solutions, or project management tools. This article walks through the most essential built-in collections, explaining their use cases, code syntax, and practical scenarios for beginners through senior engineers.
1. C# Arrays
Arrays are fixed-size, strongly typed collections used for storing simple, indexed lists of elements.
Example: Employee Array
public class Employee
{
public int Id {
get;
set;
}
public string Name {
get;
set;
}
}
// Declare and initialize
Employee[] employees = new Employee[3];
employees[0] = new Employee {
Id = 1, Name = "Kiran"
};
employees[1] = new Employee {
Id = 2, Name = "Kumar"
};
employees[2] = new Employee {
Id = 3, Name = "Mark"
};
// Access by index
Console.WriteLine(employees[1].Name); // Output: Kiran
// Iteration
foreach(var emp in employees)
Console.WriteLine($"{emp.Id}: {emp.Name}");
Key points
- Fixed size; cannot dynamically add/remove items after creation.
- Fast access via index.
- Use when the number of employees is known and unchanging.
2. Non-Generic Collections
ArrayList
- Stores objects (any type), resizes dynamically, but is not type-safe.
- Now largely obsolete—prefer generics.
using System.Collections;
ArrayList staff = new ArrayList();
staff.Add("Kiran"); // string
staff.Add(100); // int
staff.Add(new Employee {
Id = 1, Name = "Kumar"
}); // Employee object
foreach(var s in staff)
Console.WriteLine(s); // May cause runtime errors if type is unexpected!
Drawbacks: No compile-time type checking; risk of invalid casts.
3. Generic Collections
Use these for all new code. Part of System.Collections.Generic.
List<T>
Resizable, type-safe, index-accessed collection.
List < Employee > employeeList = new List < Employee >
{
new Employee {
Id = 5, Name = "Derek"
},
new Employee {
Id = 6, Name = "Kiran"
}
};
employeeList.Add(new Employee {
Id = 7, Name = "Mark"
});
foreach(var e in employeeList)
Console.WriteLine($"{e.Id}: {e.Name}");
Dictionary < TKey, TValue >
Dictionary<TKey, TValue>
Key-value pairs for lookups, e.g., by Employee ID.
Dictionary < int, Employee > directory = new Dictionary < int, Employee > ();
directory[101] = new Employee {
Id = 101, Name = "Kiran"
};
directory.Add(102, new Employee {
Id = 102, Name = "Kumar"
});
if (directory.ContainsKey(101))
Console.WriteLine(directory[101].Name); // Output: Kiran
Queue<T>
First-In-First-Out (FIFO) collection. Use for ordered tasks like employee service requests.
Queue < string > helpDesk = new Queue < string > ();
helpDesk.Enqueue("Reset Credentails for Kiran");
helpDesk.Enqueue("Setup email for Kumar");
// Process tasks
while (helpDesk.Count > 0)
Console.WriteLine("Processing: " + helpDesk.Dequeue());
Stack<T>
Last-In-First-Out (LIFO). Good for undo/redo operations or backtracking user changes.
Stack < string > employeeUndo = new Stack < string > ();
employeeUndo.Push("Added Kiran");
employeeUndo.Push("Edited Kumar");
Console.WriteLine(employeeUndo.Pop()); // Output: Edited Kumar
HashSet<T>
Unordered, unique elements. Great for storing unique employee emails or IDs.
HashSet < string > emails = new HashSet < string > ();
emails.Add("[email protected]");
emails.Add("kumar@ microsoft.com");
emails.Add("mark@ microsoft.com"); // Ignored (duplicate)
LinkedList<T>
Doubly-linked list; efficient for insertions/removals at both ends or in the middle.
LinkedList < string > activities = new LinkedList < string > ();
activities.AddLast("Interview");
activities.AddFirst("Application Received");
SortedList<TKey, TValue> & SortedDictionary<TKey, TValue>
Keep the key-order automatically. Use for sorted employee directories.
SortedList < int, string > sortedById = new SortedList < int, string > ();
sortedById.Add(2, "Kiran");
sortedById.Add(1, "Kumar");
// Now ordered by key: 1, 2
SortedSet<T>
Unique elements, always sorted. Use for unique badge numbers or sorted skill sets.
SortedSet < int > badges = new SortedSet < int > {
1004,
1001,
1003
};
foreach(var badge in badges)
Console.WriteLine(badge); // 1001, 1003, 1004
4. Specialized & Advanced Collections
Concurrent Collections
For multi-threaded applications (rare in basic employee management):
- ConcurrentDictionary<TKey, TValue>
- ConcurrentQueue<T>
- ConcurrentBag<T>
ObservableCollection<T>
For UI data binding (WPF, etc.)—auto-updates UI when collection changes.
ReadOnlyCollection<T>
Provides a read-only wrapper for existing collections when data should not be modified.
5. Choosing the Right Collection
Collection |
Best For |
Array |
Fixed size, fastest access, simple scenarios |
ArrayList |
Legacy; avoid in new code |
List<T> |
Dynamic size, fast lookups, and most general cases |
Dictionary<TKey, TValue> |
Key-based lookup (e.g., by ID) |
Queue<T> |
FIFO tasks/processes |
Stack<T> |
LIFO/undo-redo/backtracking |
HashSet<T> |
Unique, unordered elements |
LinkedList<T> |
Frequent insertions/removals anywhere |
SortedList/SortedSet<T> |
Unique + sorted, fast ordered access |
Concurrent* |
Thread-safe situations |
ObservableCollection<T> |
UI data-binding |
6. Best Practices for Engineers of All Levels
- Use generic collections (e.g., List<T>, Dictionary<TKey,TValue>) for type safety and performance.
- Avoid ArrayList and non-generic collections unless maintaining legacy code.
- Understand each collection’s strengths (lookups, order, uniqueness, sorting).
- Choose based on use case: fixed size (array), dynamic (List), lookup (Dictionary), etc.
- Use LINQ for querying and manipulating collections (bonus for advanced users).
- Favor immutability with ReadOnlyCollection<T> when exposing data publicly.
7. Entry-Level to Senior Learning
- Entry: Arrays, basic List<T>, Dictionary<TKey, TValue>
- Intermediate: Queue<T>, Stack<T>, HashSet<T>, LINQ basics
- Advanced: LinkedList<T>, Sorted* collections, custom collections, concurrent/immutable collections, LINQ mastery
Conclusion
Mastering collections is foundational for C# development. Use arrays for small, fixed groups; lists and dictionaries for dynamic, type-safe access; and select stacks, queues, sets, and advanced collections as your needs become more complex program.