Lists vs Arrays in C# – List<T>, Array, ArrayList
Introduction
Choosing the right data structure is critical to writing efficient and clean C# code. Whether you're storing a set of numbers, objects, or complex types, the decision between Array
, List<T>
, or ArrayList
can significantly impact performance and maintainability.
In this guide, we’ll compare these three major C# collection types, their syntax, use cases, advantages, and limitations. If you've ever wondered when to use a static array or why generic collections are preferred today, this deep dive is for you.
What is an Array in C#?
An Array in C# is a fixed-size collection of elements of the same type. It’s efficient in memory and ideal for scenarios where the number of elements is known ahead of time. Arrays are part of the System namespace and are one of the fundamental data structures in C#.
- Fixed Size: Once declared, its size cannot change.
- Indexed Access: Elements are accessed by zero-based index.
- Type-Safe: All elements must be of the same data type.
int[] numbers = new int[5];
numbers[0] = 10;
numbers[1] = 20;
Console.WriteLine(numbers[1]);
Declaring and Initializing Arrays
You can declare and initialize arrays in several ways depending on your needs. Arrays can also be multidimensional or jagged for storing matrices or nested data.
Single-Dimensional Array
string[] fruits = new string[] { "Apple", "Banana", "Cherry" };
Multi-Dimensional Array
int[,] matrix = new int[2, 2] {
{1, 2},
{3, 4}
};
Jagged Array
int[][] jaggedArray = new int[2][];
jaggedArray[0] = new int[] { 1, 2 };
jaggedArray[1] = new int[] { 3, 4, 5 };
What is a List<T>?
List<T>
is a generic collection in C# that grows and shrinks dynamically. It’s part of the System.Collections.Generic namespace and is preferred over arrays in modern C# development for its flexibility and built-in methods.
Advantages:
- Dynamic resizing – no need to declare size upfront.
- Generic – type-safe and avoids boxing/unboxing.
- Feature-rich – provides
Add
,Remove
,Find
,Sort
, etc.
List<string> names = new List<string>();
names.Add("Alice");
names.Add("Bob");
Console.WriteLine(names[0]);
What is an ArrayList?
ArrayList
is a non-generic collection that stores elements as objects. It was widely used in early .NET versions before generics were introduced in .NET 2.0. Being part of the System.Collections
namespace, ArrayList
can store any type but lacks the type safety and performance benefits of generic collections like List<T>
.
Drawbacks of ArrayList:
- Not type-safe – stores objects, leading to runtime errors.
- Requires boxing/unboxing for value types – reduces performance.
- Lacks compile-time type checking.
However, it’s still useful for legacy code and when working with non-generic APIs.
Declaring and Using ArrayList
You can create and manipulate an ArrayList
just like a List<T>
, but with less strict typing.
ArrayList items = new ArrayList();
items.Add("Text");
items.Add(123); // Allows mixing types
items.Add(true);
Console.WriteLine(items[1]); // Outputs: 123
Boxing and Unboxing in ArrayList
When you add a value type (like int) to an ArrayList
, it is "boxed" into an object. Retrieving it requires "unboxing," which can be costly in terms of performance.
int number = 100;
ArrayList list = new ArrayList();
list.Add(number); // Boxing
int unboxed = (int)list[0]; // Unboxing
This overhead is one reason why developers now prefer List<T>
over ArrayList
.
Differences Between Array, List<T>, and ArrayList
Let’s compare all three to understand which one fits your needs better:
Feature | Array | List<T> | ArrayList |
---|---|---|---|
Namespace | System | System.Collections.Generic | System.Collections |
Type Safety | Yes | Yes (Generic) | No |
Resizable | No | Yes | Yes |
Performance | Fast | Fast | Slower due to boxing/unboxing |
Recommended? | Yes (for fixed size) | Yes (most use cases) | Only for legacy support |
As you can see, List<T> is often the best choice for modern C# development, combining performance with flexibility. Arrays work well when size is fixed and performance is critical. ArrayList
is mainly for compatibility with old codebases.
Use Cases for Array, List<T>, and ArrayList
Each of these data structures fits different scenarios based on performance, type safety, and mutability needs. Here’s when to choose each:
When to Use Array
- You know the exact number of elements ahead of time.
- You’re working with performance-critical code (e.g., image processing, math computations).
- You’re interacting with low-level memory operations or native interop.
When to Use List<T>
- You need to add/remove elements frequently.
- Type safety and generics are important.
- You’re working with LINQ or need easy searching and filtering.
When to Use ArrayList
- You’re maintaining legacy .NET applications.
- You need a non-generic collection for dynamic type storage (not recommended for new apps).
- You're forced to use APIs that still require
System.Collections
.
Performance Comparison
Here’s how they stack up in typical usage scenarios:
- Array: Fastest for fixed-size, sequential access. No overhead from boxing or resizing.
- List<T>: Slightly slower than arrays, but more flexible. Resizing adds overhead on insert.
- ArrayList: Slowest due to boxing/unboxing and lack of generics.
Let’s look at an example of adding 1000 elements to each collection:
// List<T>
List<int> list = new List<int>();
for (int i = 0; i < 1000; i++)
{
list.Add(i);
}
// Array (pre-sized)
int[] array = new int[1000];
for (int i = 0; i < 1000; i++)
{
array[i] = i;
}
// ArrayList (boxing)
ArrayList arrayList = new ArrayList();
for (int i = 0; i < 1000; i++)
{
arrayList.Add(i); // Boxing happens here
}
Memory Considerations
Arrays are more memory efficient as they don’t require resizing and store elements directly. List<T>
uses dynamic arrays under the hood and may over-allocate to reduce resizing frequency. ArrayList
stores everything as object
, which increases memory usage, especially for value types.
- Array: No overhead; tight memory footprint.
- List<T>: Slight overhead from resizing but optimized.
- ArrayList: High memory usage due to boxing/unboxing.
Consider this when developing for constrained environments like embedded systems or high-performance backend systems.
Interoperability with APIs
Some legacy .NET APIs expect ArrayList
or Array
types. In those cases, you might need to convert:
// Convert List<T> to Array
int[] numberArray = numberList.ToArray();
// Convert Array to List<T>
List<int> numberList = new List<int>(numberArray);
// Convert List<T> to ArrayList (not ideal)
ArrayList listToArrayList = new ArrayList(numberList);
Conclusion
Choosing the right data structure—Array, List<T>, or ArrayList—can have a major impact on your C# application’s performance, readability, and reliability.
- Use Array for fast, fixed-size storage with minimal overhead.
- Use List<T> for dynamic, type-safe, high-level collection manipulation.
- Use ArrayList only for legacy compatibility or mixed-type storage (and even then, with caution).
In most modern scenarios, List<T> is the preferred choice—it’s versatile, generic, and well-optimized. Arrays still shine when memory layout and performance matter. ArrayLists, though largely outdated, can help you understand the evolution of collections in .NET.
Now that you know the pros, cons, and best practices for each, you're ready to choose the right tool for the job and write better, faster C# code.
FAQs
1. Can I resize an Array in C#?
No. Arrays have a fixed size after declaration. Use List<T>
if you need resizable collections.
2. Is List<T> faster than Array?
Not always. Arrays are slightly faster for fixed-size operations, but List<T>
is more flexible and better for dynamic collections.
3. Should I use ArrayList in new projects?
No. ArrayList
is non-generic and less efficient. Use List<T>
or other generic collections instead.
4. How does List<T> handle resizing?
List<T>
doubles its internal array size when more space is needed. This helps balance performance and memory usage.
5. Can I store different types in List<T>?
No. List<T>
is type-safe. To store mixed types, use List<object>
or consider using patterns like inheritance or interfaces.
Post a Comment