Lists vs Arrays in C# – List<T>, Array, ArrayList

Lists vs Arrays in C# – List<T>, Array, ArrayList

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

Post a Comment (0)

Previous Post Next Post

ads

ads

Update cookies preferences