An array has a fixed size, while ArrayList and List<T> grow as you add items. Arrays and List<T> are type-safe, and ArrayList is not.
ArrayList stores everything as object. Adding an int boxes it, and nothing stops you mixing strings and numbers in one list. The mistake shows up at run time as a failed cast. List<T> is generic, so the compiler checks every Add, and at run time it stores value types without boxing.
Array
ArrayList
List<T>
Size
Fixed
Grows
Grows
Type-safe
Yes
No
Yes
Boxes value types
No
Yes
No
Use it for
Fixed-size data, best performance
Legacy code only
Most collections
All three use zero-based indexing. Prefer List<T> in new code, and an array when the size is known and fixed.
// Array
int[] array = new int[5];
// ArrayList (avoid)
ArrayList arrayList = new ArrayList();
arrayList.Add(1); // Boxing occurs
arrayList.Add("text"); // No compile-time type checking
// List<T> (preferred)
List<int> list = new List<int>();
list.Add(1); // No boxing
// list.Add("text"); // Compile-time error
Rewriting in plainer words…
This answer doesn't lend itself to a diagram - it reads best . No credits were charged.
Saved in this browser - sign in to keep your review list.
How should your speech become text?
Listening… your words appear above as you speak - tap Stop when you're done.
Recording · cr - tap Stop & transcribe when you're done.
Transcribing with AI…
Voice:
Keep going - a few more words and AI can grade it.
Interview lens
How interviewers actually use this question
Likely follow-ups
What happens inside a List<T> when you add an item and it is already at capacity?It allocates a larger backing array, roughly double, and copies the items across. Passing the expected count to the constructor avoids repeated copies.
Should a public method return List<T>, or something else?Return the narrowest type the caller needs, like IReadOnlyList<T> or IEnumerable<T>, so callers can't change your internal list.
Arrays in C# are covariant. What can go wrong that List<T> prevents?Assign a string[] to object[], store an int, and it throws ArrayTypeMismatchException at run time. List<T> is invariant, so that won't compile.
What you can say
An array has a fixed size, while ArrayList and List<T> both grow as you add items.
Arrays and List<T> are type-safe, and ArrayList isn't, because it stores everything as object.
So adding an int to an ArrayList boxes it, and nothing stops you mixing strings and numbers, so the bug only shows up at run time as a failed cast.
List<T> is generic, so the compiler checks every Add, and at run time it stores value types like int without boxing.
All three use zero-based indexing, so day-to-day access looks the same.
In new code I default to List<T>, use an array when the size is known and fixed, and leave ArrayList to legacy code.
Weak answers to avoid
Treats ArrayList and List<T> as the same thingThey differ where it matters. ArrayList stores object, so ints get boxed and type errors surface at run time. List<T> is checked at compile time.
Calls List<T> a linked listList<T> is backed by an array that it resizes, so indexing is as fast as an array. Calling it a linked list gets indexing and insert costs wrong.
Recites the table without the reasonSaying ArrayList isn't type-safe is half an answer. Explain that it stores object, so a bad cast fails at run time instead of at compile time.
Suggests ArrayList when items have mixed typesMixing types is the bug ArrayList fails to catch. If the items share behavior, use a List<T> of their common base class or interface.
Interview lens
Likely follow-ups, what you can say, and the weak answers to avoid.