TL;DR

  • ArrayList is an obsolete non-generic collection from pre-2005 .NET that stores everything as object
  • Using ArrayList causes performance issues due to boxing/unboxing of value types
  • ArrayList lacks compile-time type safety, leading to runtime exceptions
  • List<T> and other generic collections offer superior performance, type safety, and developer experience
  • Boxing/unboxing with ArrayList can make code up to 10x slower in computation-heavy scenarios
  • Modern C# code should always use strongly-typed collections like List<T>, Dictionary<TKey,TValue>, etc.
  • Even when storing mixed types, prefer List<object> over ArrayList for consistency

If you’re still using ArrayList in your C# projects, you’re basically driving a horse-drawn carriage on a highway. Sure, it’ll get you there, but everyone’s zooming past you with better tools. Here’s why ArrayList belongs in the .NET history books and what you should use instead.

What is ArrayList and Why Did It Exist?

Back when .NET was new (before 2005), we didn’t have generics. ArrayList was the standard way to create dynamic collections for mixed types. It lives in the System.Collections namespace and can hold any object, strings, integers, custom classes, whatever you need.

// The old way - ArrayList can hold anything
ArrayList oldList = new ArrayList();
oldList.Add("Hello");
oldList.Add(42);
oldList.Add(new DateTime(2024, 1, 1));
// This compiles fine, but creates problems later

The Modern Alternative: List

When generics arrived in .NET 2.0, List<T> changed everything. Instead of storing everything as object, you specify exactly what type you want to store.

// The modern way - type-safe and performant
List<string> modernList = new List<string>();
modernList.Add("Hello");
// modernList.Add(42); // Compile error - can't add int to List<string>

Why ArrayList Hurts Your Code

1. Boxing and Unboxing Performance Hit

Every time you add a value type to an ArrayList, .NET boxes it into an object. When you retrieve it, you need to unbox it. This creates extra work for garbage collection and tanks your performance.

// ArrayList boxes integers - expensive!
ArrayList numbers = new ArrayList();
numbers.Add(1); // Boxing happens here
int first = (int)numbers[0]; // Unboxing and casting required

// List<T> stores values directly - fast!
List<int> betterNumbers = new List<int>();
betterNumbers.Add(1); // No boxing
int first = betterNumbers[0]; // Direct access, no casting

2. Runtime Errors from Type Confusion

ArrayList compiles successfully but can explode at runtime when you cast to the wrong type.

ArrayList mixed = new ArrayList();
mixed.Add("text");
mixed.Add(123);

// This compiles but crashes at runtime
string text = (string)mixed[1]; // InvalidCastException!

3. No IntelliSense Love

Since ArrayList returns object, you lose all type information and IntelliSense support.

ArrayList vs List: The Comparison

FeatureArrayListList
Type SafetyRuntime onlyCompile-time
PerformanceBoxing/unboxing overheadDirect storage
IntelliSenseLimited (returns object)Full type support
Casting RequiredAlwaysNever
Memory UsageHigher (boxing)Lower
Runtime ErrorsCommonRare

See here the detailed comparison of ArrayList and List<T>.

Common Pitfalls I’ve Seen

I’ve fixed so many bugs where developers mixed types in ArrayList and got crashes when casting at runtime. The worst part? These bugs sneak into production because they compile without errors.

Another problem: loops get super slow when boxing/unboxing happens thousands of times. I once worked on a data processing app that ran 10x slower just because it used ArrayList for number crunching.

The Bottom Line

Using ArrayList in modern C# is like watching VHS tapes in a streaming world. The old tech still works, but you’re missing out on huge improvements in safety, speed, and coding experience.

Don’t use ArrayList in modern C#. Go with List<T>, IEnumerable<T>, or other generic collections instead. Your future self (and your teammates) will thank you for writing code that’s type-safe, fast, and clearly shows what it does.

Generics changed C# for a reason, use them.

Related Posts