Arrays are crude versions of List’s. They work the same, with one huge drawback: they have a permanent size which can’t change. That’s pretty bad. You want Lists for almost everything.
We learn about arrays because they’re the real way computers store sequences. They’re built into many languages. Lists are actually made using arrays. Many built-in functions use arrays because they’re simple, often good enough, and you can turn them into Lists if you need.
Array index loops use N[i] and N.Length. This sets everything in an array to 0:
Besides Length instead of Count, this is identical to how a List does
it.
Like List’s, arrays are a 2-part type. [] means some sort of array, with the type in front. int[] means “array of ints”. Others:
Don’t confuse the square brackets with indexing. This is a special use for
declaring. The inside is always empty. int[] is the only way to do it.
C# arrays are reference types. They start as null and need to be created with new. You’re required to give them the permanent size, in square brackets:
This is another completely new rule and a different use for [5]. Again, don’t
confuse it with an index.
All of the rules together, this makes a size 10 array full of the word cat:
The rule where arrays can never change size goes together with the rule where you have to give a starting size in the new. Without being able to add items, the only way an array can ever get a size is during creation.
It has to do with how memory works. Memory is like a line of boxes and things tend to be created from one end. After you new a size 10 array, the next things you create will come immediately after. There’s no room to grow most arrays. Even if there were, the memory allocator isn’t really set up to grow an existing chunk.
Functions take arrays as inputs and outputs in the usual way. As before, int[] means it takes an array of int’s. The input array can be any size. For example, this counts how many of a certain number are in an array:
It looks the same as the List version, except for int[] instead of List<int> and
Length instead of Count.
Because they’re pointers, you can use a function to change the contents of an array. This makes every number be even. The array we give it will be changed:
Returning an array uses the same syntax: string[] in front means it returns an array of strings. This creates and returns an array of the size you want, filled with the word you give it:
We could use it like string[] A=makeSameWordArray(5,"cat");.
An advantage of L.Add(3) with Lists is not needing to know the final size in advance. Since arrays need to know, making an array often has 2 steps. First we count how long it needs to be, then we create it and fill it up.
This returns an array with all of the words longer than 3 letters:
Notice how we needed an extra index for the answer in the second loop. Suppose
it turns out the final list should have items 2, 5, 6 and 9. We need ri so we can copy
those into 0, 1, 2, and 3 of the result. It was a lot easier being able to use
Result.Add(A[i]);.
Adding 2 arrays end-to-end isn’t as bad. We know the final size is the sum of the sizes, but we need math to add the second to the end:
If we had a List, the second loop would be simply C.Add(B[i]);.
Arrays can change size, sort of. We can create new empty array, 1 box larger; copy everything over; then aim at the new array. This adds "zebra" to the end of string array W:
The old array is abandoned and garbage-collected. That works, but if we add a lot it’s slow and makes a ton of garbage.
We often fake an array that can grow by making it the maximum size and marking how much we really use with an extra int:
The end result: wsz is 2. W counts as size 2. And W[0] and W[1] are our animals.
We usually put them in a class:
It’s the same trick, but using a class covers it up and makes it easier to
use.
When we search the list, we have to remember to use i<sz instead of
i<W.Length.
This is actually how the List class works. It has a hidden array. But instead of quitting when the array is full, it creates a new array twice as big and copies.
Because arrays are built-in, they have an easy shortcut for making them pre-filled. {2,8,6} makes a size 3 array with those numbers. It can only be used when the array is declared:
The system counts the items, creates an array that size, and fills it with those
values. As usual, there’s nothing special about starting values. You can change them
later.
To use the shortcut anywhere else, you need extra in front. Add new int[]:
As with most array syntax, it’s not part of a pattern or larger rule. It works that
way because that’s the rule we made.
You can even use it inside a function call, often for testing:
Lists have a constructor taking an array as input:
We often use it with the array-creating shortcut. It’s long, but shorter than hand-adding everything:
Lists have a function to return an array of what they are:
It makes a copy, so we can change the contents of N without changing L.
A common use for this is a function that takes an array as input, when we have it in a list:
Unity’s OverlapSphere function returns an array. You call it with an imaginary ball, in the 3D world. It tells you every Cube, Ball and so on partly inside of it. This finds everything within 2 spaces of (0,5,0):
It returns an array of Colliders (they go on gameObjects). It’s an array instead of
a List since all you’re going to do is look through it. An array is fine for
that.
Every time you run it, a new array is created and thrown away when you’re done. That’s not a big deal. But OverlapSphere has a version which re-uses your array. You make one as big as you think you need and hand it over. OverlapSphere fills it and returns how many there were:
If you overlapped 3 things, they would be in 0-2 of H, the return value would be 3,
and the rest of H would be old junk values.
If you remember, 2D lists are just lists of lists – no extra rules needed. Arrays have that method, sort of, plus they have a special perfect-rectangle version.
These are mostly good as examples of the crazy rules people jam into computer languages.
An array of arrays is mostly like a list of lists, except for one funny rule. Write two pairs of []’s in the definition:
This would make A be 3 by 4:
Like with lists, A[0] is the first row. It’s a single length four array: A[0].Length
is four. A[0][0] is one int in the grid.
We call these ragged arrays since each row could be a different length. We made them all length 4, but they didn’t have to be.
C# also includes an older special syntax to make perfectly rectangular 2D arrays. A “real” 2D 3 by 4 array would be created like this:
It comes with a special version of the insta-array shortcut:
The rule for finding the lengths is fun, since it has 2 lengths. M.Length tells you the total number of items – 12 – which isn’t very helpful.
M.GetLength(i) gets the size of each dimension, starting at 0. M.Rank tells you how many dimensions it has (1 is a normal array, 2 is 2D, and so on).
This uses them in a double-loop to change everything to 7’s in any sized 2D array: