As others have said, it depends on the type semantics that you're putting into the array.
Value types (such as int
, bool
, and float
) are ... well, values. They represent a quantity, something tangible, a state. Thus, they are required to be known at compile time and have a default value.
By contrast, reference types (basically every class) don't actually hold any values themselves, but "group" data together by means of reference. Reference types will either point to other reference types, or eventually to a value type (which holds actual data).
This distinction is important to your question. List<T>
is a dynamically sized collection that can grow or shrink without creating a new object because of how it is implemented. Each element in the list points to the next element, thus it's size cannot be known ahead of time.
Arrays are a fixed-size collection that are declared to be a specific size. The type of array determines how much memory is reserved by the system. For example a byte[]
of 100 elements will consume less memory than an Int64[]
array of 100 elements. Thus, the system needs to know ahead of time how many bytes to reserve in total, which means it needs a default value to "fall back" on to satisfy compile-time checking. Where T[]
is a reference type/class, this is null
. For value types, this is usually 0
(or default(T)
).
If you wanted to remove all the values of an array, similar to how List.Clear()
works, you can do int[] a = new int[0];
, but note that you are creating an entirely new array and reallocating the memory for them (hence the keyword new
). Other objects will need to reference this new array. By design, you can't simply resize an array. A list is a mutable collection and supports changing the number of elements. You could also try int[] a = null
, but this sets it to no object at all, which is again, something different.