Collections are a fundamental part of any application that manages data. In C#, you have two primary options for working with collections: generic and non-generic.
But what exactly are they, and when should you use one over the other?
In this article, we’ll break down the key differences between the two, highlight their impact on performance and usability.
What Are Collections in C#?
Collections are classes used to store, manage, and manipulate groups of related objects.
These collections fall into two categories:
- Generic Collections
- Non-Generic Collections
Generic Collections
Type-Safe by Design
Generic collections require you to define the type of data they will hold. For example, List<int> will only accept integers.
This ensures:
- No accidental data type mismatches
- No need for casting
Better Performance
Since there’s no need for boxing/unboxing (converting value types to/from object), generic collections perform faster and use memory more efficiently.
Common Generic Collections
List<string> names = new List<string>();
Dictionary<int, string> studentMap = new Dictionary<int, string>();
Queue<double> prices = new Queue<double>();
HashSet<Guid> uniqueIds = new HashSet<Guid>();
Non-Generic Collections
Object-Based Storage
Non-generic collections store data as object, which leads to the need for casting when retrieving data.
This can result in:
- Runtime errors if the cast is incorrect
- Lower performance due to boxing/unboxing
Common Non-Generic Collections
ArrayList items = new ArrayList();
items.Add(42);
items.Add("hello"); // Works, but can cause issues later
Hashtable map = new Hashtable();
map["id"] = 1;
map["name"] = "Alice";
Performance Comparison
When you work with large amounts of data, the cost of boxing/unboxing and casting becomes significant.
Example
ArrayList list = new ArrayList();
// Value type is boxed
list.Add(1);
// Unboxed and cast manually
int number = (int)list[0];
VS
List<int> list = new List<int>();
// No boxing required
list.Add(1);
// Clean and safe
int number = list[0];
Benchmarking
These are benchmarking result of adding, and iterate throw elements for both type of collections.
![Benchmarking]()
Conclusion
Generic collections are the default choice for modern .NET development providing type safety, clarity, and performance. Non-generic collections still exist for backward compatibility but are largely obsolete for most use cases.
Choose wisely and your application will thank you with fewer bugs and better performance.