int[] numbers;
new int[5];
, where the number in square brackets is the number of items in the array.numbers[0] = 15;
. The index is in square brackets, and starts at 0.Console.WriteLine(numbers[4]);
Imagine you are building a game with a high scores table. You want ten scores to be displayed.
Using tools we already know, you could imagine doing something like this:
int score1 = 1000;
int score2 = 950;
int score3 = 925;
// ...
Writing out ten score variables like that is not so bad. But if we wanted 20 or 100 or 1000 scores… well… it just gets worse and worse.
This is where arrays come in. An array is a way to declare a whole group of related variables together. Or, perhaps, stated more correctly, it creates a single container to hold many values of the same type, all of which can be stored in a single variable.
To create an array that holds int
values, the declaration for the variable would look something like this:
int[] scores;
Square brackets ([
and ]
) are a common sight with arrays (and other collection types).
We’ll be seeing them a lot as we go forward.
Here, the scores
variable is not for a single int
, but for an array of int
s.
To initialize it, we need to create an array of a certain size. That can be done with code like this:
int[] scores = new int[10];
That tells the program to find a place in memory to store 10 int
values together.
The scores
variable ends up holding a reference
to where that data got placed in memory.
We’ll learn more about references as we go, but for now, think of a reference as a way to look up another place in memory.
An analogy might be that it is like a phone number, email address, or the Bat Signal–a way to find the data when you need it.
So scores
doesn’t contain the 10 int
values directly, but we can work through it to access those values.
This model is a bit different from many of the other types we have discussed so far, like int
, double
, and bool
, where the variable holds that actual data, no reference necessary.
Those types are all in a category called value types
.
They store their data directly.
Arrays (and string
as well) are in a second category called reference types
.
Variables that are reference types hold a reference, not the actual data.
The reference can be used to hunt down the data.
That single difference may not seem like much, but it has a lot of consequences that we’ll explore as we move forward.
warning
This value type vs. reference type concept is one of the key ways C# differs from other very similar languages, like Java and C++. If you have been going through these tutorials fast because you already know one of these other similar languages, stop and make sure you have a grasp on this important concept.
Once we have created an array, we’re ready to work with individual elements within an array.
To do this, you access them by index–and the first index is 0!
warning
Indices (or indexes) start at 0, not 1! That is extremely important to remember. It will likely come as a big surprise if you haven’t programmed before, or if you’ve only programmed in languages that start at 1.
To store a value at a specific spot in an array, do the following:
scores[0] = 1000;
Using the variable name, followed by square brackets containing the index you want (remember, this starts at 0!), lets you assign values to this spot.
To read a value out of a specific spot in an array, do the following:
Console.WriteLine("The highest score has a value of " + scores[0]);
The index can be any int
-typed expression.
I’ve used literals here for simplicity, but you could use any expression you want to calculate the index you’re looking for:
for (int index = 0; index < 10; index++)
Console.WriteLine(scores[index]);
note
Notice how index
starts at 0
and goes up to 10
, but not including it. (We’re using <
, not <=
.)
This is an extremely common idiom in C# programming, and you’ll see it everywhere.
Since array indices start at 0, it makes more sense to have your for
loop variable start at 0 as well, and then repeat for the right number of times to get to the end of the array.
Since scores
has 10 items in it, doing <= 10
will mean we loop 10 times.
foreach
LoopWhile we’re on the subject of looping through an array, let’s cover the final type of loop in C#: the foreach
loop.
The previous code above uses a for
loop to walk down the whole array from start to finish.
We could have used a foreach
loop instead, which removes the index
variable entirely:
foreach(int score in scores)
Console.WriteLine(score);
If all you want to do is walk down the collection one at a time and do something with them, the foreach
loop is the simplest, clearest code you could write.
Length
PropertyThere is a danger to this type of code:
int[] scores = new int[10];
for (int index = 0; index < 10; index++)
Console.WriteLine(scores[index]);
That danger arises when you decide to change the number of scores you want to track from 10 to, say, 20.
It is easy to change one of those occurrences of 10
and forget the other, and then we’ll have a problem.
There’s a better way.
Each array has a Length
property on it, which we can use to check its length.
By using this in the for
loop, it will be resilient to changes in how long the array is:
int[] scores = new int[20];
for (int index = 0; index < scores.Length; index++)
Console.WriteLine(scores[index]);
If you know exactly which items you want in an array from the beginning, there are some shortcuts for populating the array:
int[] scores = new int[5] { 1000, 900, 800, 600, 200 };
In fact, given that the C# compiler can figure out how long the array should be, you can always leave out the length when doing this:
int[] scores = new int[] { 1000, 900, 800, 600, 200 };
We can often do even better.
If the type can be inferred (such as the fact that every value we put in the array is an int
literal above), then we can even leave off the type:
int[] scores = new [] { 1000, 900, 800, 600, 200 };
You can make arrays of any type out there.
Our examples have all been arrays of int
so far, but we could do string[]
or bool[]
or double[]
or anything else.
That also includes arrays of arrays of something:
int[][] twoDimensionalArray = new int[3][];
twoDimensionalArray[0] = new int[10];
twoDmensionalArray[1] = new int[20];
twoDimensionalArray[2] = new int[40];
twoDmensionalArray[1][11] = 3;
Of course, it takes a bit of code to build that out, because in order to use each item in the main array, you need to use new
to create an array for each spot in that array.
This approach allows each array within the main array to be a different size. This is called a jagged array .
But often, you don’t need that–you want every child array to be the same length. You want a rectangular array .
There’s a simpler way to make a rectangular array:
int[,] twoDimensionalArray = new int[3, 10];
twoDimensionalArray[0, 5] = -1;
Console.WriteLine(twoDimensionalArray[0, 5]);
Multi-dimensional arrays are great when you need to represent a grid structure somehow. That is a common need in certain types of games.